• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package android.app.assist;
2 
3 import android.annotation.NonNull;
4 import android.annotation.Nullable;
5 import android.annotation.SuppressLint;
6 import android.annotation.SystemApi;
7 import android.app.Activity;
8 import android.content.ComponentName;
9 import android.content.Context;
10 import android.graphics.Matrix;
11 import android.graphics.Rect;
12 import android.net.Uri;
13 import android.os.BadParcelableException;
14 import android.os.Binder;
15 import android.os.Bundle;
16 import android.os.IBinder;
17 import android.os.LocaleList;
18 import android.os.Parcel;
19 import android.os.Parcelable;
20 import android.os.PooledStringReader;
21 import android.os.PooledStringWriter;
22 import android.os.RemoteException;
23 import android.os.SystemClock;
24 import android.service.autofill.FillRequest;
25 import android.text.TextUtils;
26 import android.util.Log;
27 import android.util.Pair;
28 import android.view.View;
29 import android.view.View.AutofillImportance;
30 import android.view.ViewRootImpl;
31 import android.view.ViewStructure;
32 import android.view.ViewStructure.HtmlInfo;
33 import android.view.ViewStructure.HtmlInfo.Builder;
34 import android.view.WindowManager;
35 import android.view.WindowManagerGlobal;
36 import android.view.autofill.AutofillId;
37 import android.view.autofill.AutofillValue;
38 
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.List;
42 import java.util.Objects;
43 
44 /**
45  * <p>This API automatically creates assist data from the platform's
46  * implementation of assist and autofill.
47  *
48  * <p>The structure is used for assist purposes when created by
49  * {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)},
50  * or {@link View#onProvideVirtualStructure(ViewStructure)}.
51  *
52  * <p>The structure is also used for autofill purposes when created by
53  * {@link View#onProvideAutofillStructure(ViewStructure, int)},
54  * or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}.
55  *
56  * <p>For performance reasons, some properties of the assist data might only be available for
57  * assist or autofill purposes. In those cases, a property's availability will be documented
58  * in its javadoc.
59  *
60  * <p>To learn about using Autofill in your app, read the
61  * <a href="/guide/topics/text/autofill">Autofill Framework</a> guides.
62  */
63 public class AssistStructure implements Parcelable {
64     private static final String TAG = "AssistStructure";
65 
66     private static final boolean DEBUG_PARCEL = false;
67     private static final boolean DEBUG_PARCEL_CHILDREN = false;
68     private static final boolean DEBUG_PARCEL_TREE = false;
69 
70     private static final int VALIDATE_WINDOW_TOKEN = 0x11111111;
71     private static final int VALIDATE_VIEW_TOKEN = 0x22222222;
72 
73     private boolean mHaveData;
74 
75     // The task id and component of the activity which this assist structure is for
76     private int mTaskId;
77     private ComponentName mActivityComponent;
78     private boolean mIsHomeActivity;
79     private int mFlags;
80     private int mAutofillFlags;
81 
82     private final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
83 
84     private final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
85 
86     private SendChannel mSendChannel;
87     private IBinder mReceiveChannel;
88 
89     private Rect mTmpRect = new Rect();
90 
91     private boolean mSanitizeOnWrite = false;
92     private long mAcquisitionStartTime;
93     private long mAcquisitionEndTime;
94 
95     private static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
96     private static final String DESCRIPTOR = "android.app.AssistStructure";
97 
98     /** @hide */
setAcquisitionStartTime(long acquisitionStartTime)99     public void setAcquisitionStartTime(long acquisitionStartTime) {
100         mAcquisitionStartTime = acquisitionStartTime;
101     }
102 
103     /** @hide */
setAcquisitionEndTime(long acquisitionEndTime)104     public void setAcquisitionEndTime(long acquisitionEndTime) {
105         mAcquisitionEndTime = acquisitionEndTime;
106     }
107 
108     /**
109      * @hide
110      * Set the home activity flag.
111      */
setHomeActivity(boolean isHomeActivity)112     public void setHomeActivity(boolean isHomeActivity) {
113         mIsHomeActivity = isHomeActivity;
114     }
115 
116     /**
117      * Returns the time when the activity started generating assist data to build the
118      * AssistStructure. The time is as specified by {@link SystemClock#uptimeMillis()}.
119      *
120      * @see #getAcquisitionEndTime()
121      * @return Returns the acquisition start time of the assist data, in milliseconds.
122      */
getAcquisitionStartTime()123     public long getAcquisitionStartTime() {
124         ensureData();
125         return mAcquisitionStartTime;
126     }
127 
128     /**
129      * Returns the time when the activity finished generating assist data to build the
130      * AssistStructure. The time is as specified by {@link SystemClock#uptimeMillis()}.
131      *
132      * @see #getAcquisitionStartTime()
133      * @return Returns the acquisition end time of the assist data, in milliseconds.
134      */
getAcquisitionEndTime()135     public long getAcquisitionEndTime() {
136         ensureData();
137         return mAcquisitionEndTime;
138     }
139 
140     final static class SendChannel extends Binder {
141         volatile AssistStructure mAssistStructure;
142 
SendChannel(AssistStructure as)143         SendChannel(AssistStructure as) {
144             mAssistStructure = as;
145         }
146 
onTransact(int code, Parcel data, Parcel reply, int flags)147         @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
148                 throws RemoteException {
149             if (code == TRANSACTION_XFER) {
150                 AssistStructure as = mAssistStructure;
151                 if (as == null) {
152                     return true;
153                 }
154 
155                 data.enforceInterface(DESCRIPTOR);
156                 IBinder token = data.readStrongBinder();
157                 if (DEBUG_PARCEL) Log.d(TAG, "Request for data on " + as
158                         + " using token " + token);
159                 if (token != null) {
160                     if (DEBUG_PARCEL) Log.d(TAG, "Resuming partial write of " + token);
161                     if (token instanceof ParcelTransferWriter) {
162                         ParcelTransferWriter xfer = (ParcelTransferWriter)token;
163                         xfer.writeToParcel(as, reply);
164                         return true;
165                     }
166                     Log.w(TAG, "Caller supplied bad token type: " + token);
167                     // Don't write anything; this is the end of the data.
168                     return true;
169                 }
170                 //long start = SystemClock.uptimeMillis();
171                 ParcelTransferWriter xfer = new ParcelTransferWriter(as, reply);
172                 xfer.writeToParcel(as, reply);
173                 //Log.i(TAG, "Time to parcel: " + (SystemClock.uptimeMillis()-start) + "ms");
174                 return true;
175             } else {
176                 return super.onTransact(code, data, reply, flags);
177             }
178         }
179     }
180 
181     final static class ViewStackEntry {
182         ViewNode node;
183         int curChild;
184         int numChildren;
185     }
186 
187     final static class ParcelTransferWriter extends Binder {
188         final boolean mWriteStructure;
189         int mCurWindow;
190         int mNumWindows;
191         final ArrayList<ViewStackEntry> mViewStack = new ArrayList<>();
192         ViewStackEntry mCurViewStackEntry;
193         int mCurViewStackPos;
194         int mNumWrittenWindows;
195         int mNumWrittenViews;
196         final float[] mTmpMatrix = new float[9];
197         final boolean mSanitizeOnWrite;
198 
ParcelTransferWriter(AssistStructure as, Parcel out)199         ParcelTransferWriter(AssistStructure as, Parcel out) {
200             mSanitizeOnWrite = as.mSanitizeOnWrite;
201             mWriteStructure = as.waitForReady();
202             out.writeInt(as.mFlags);
203             out.writeInt(as.mAutofillFlags);
204             out.writeLong(as.mAcquisitionStartTime);
205             out.writeLong(as.mAcquisitionEndTime);
206             mNumWindows = as.mWindowNodes.size();
207             if (mWriteStructure && mNumWindows > 0) {
208                 out.writeInt(mNumWindows);
209             } else {
210                 out.writeInt(0);
211             }
212         }
213 
writeToParcel(AssistStructure as, Parcel out)214         void writeToParcel(AssistStructure as, Parcel out) {
215             int start = out.dataPosition();
216             mNumWrittenWindows = 0;
217             mNumWrittenViews = 0;
218             boolean more = writeToParcelInner(as, out);
219             Log.i(TAG, "Flattened " + (more ? "partial" : "final") + " assist data: "
220                     + (out.dataPosition() - start)
221                     + " bytes, containing " + mNumWrittenWindows + " windows, "
222                     + mNumWrittenViews + " views");
223         }
224 
writeToParcelInner(AssistStructure as, Parcel out)225         boolean writeToParcelInner(AssistStructure as, Parcel out) {
226             if (mNumWindows == 0) {
227                 return false;
228             }
229             if (DEBUG_PARCEL) Log.d(TAG, "Creating PooledStringWriter @ " + out.dataPosition());
230             PooledStringWriter pwriter = new PooledStringWriter(out);
231             while (writeNextEntryToParcel(as, out, pwriter)) {
232                 // If the parcel is above the IPC limit, then we are getting too
233                 // large for a single IPC so stop here and let the caller come back when it
234                 // is ready for more.
235                 if (out.dataSize() > IBinder.MAX_IPC_SIZE) {
236                     if (DEBUG_PARCEL) Log.d(TAG, "Assist data size is " + out.dataSize()
237                             + " @ pos " + out.dataPosition() + "; returning partial result");
238                     out.writeInt(0);
239                     out.writeStrongBinder(this);
240                     if (DEBUG_PARCEL) Log.d(TAG, "Finishing PooledStringWriter @ "
241                             + out.dataPosition() + ", size " + pwriter.getStringCount());
242                     pwriter.finish();
243                     return true;
244                 }
245             }
246             if (DEBUG_PARCEL) Log.d(TAG, "Finishing PooledStringWriter @ "
247                     + out.dataPosition() + ", size " + pwriter.getStringCount());
248             pwriter.finish();
249             mViewStack.clear();
250             return false;
251         }
252 
pushViewStackEntry(ViewNode node, int pos)253         void pushViewStackEntry(ViewNode node, int pos) {
254             ViewStackEntry entry;
255             if (pos >= mViewStack.size()) {
256                 entry = new ViewStackEntry();
257                 mViewStack.add(entry);
258                 if (DEBUG_PARCEL_TREE) Log.d(TAG, "New stack entry at " + pos + ": " + entry);
259             } else {
260                 entry = mViewStack.get(pos);
261                 if (DEBUG_PARCEL_TREE) Log.d(TAG, "Existing stack entry at " + pos + ": " + entry);
262             }
263             entry.node = node;
264             entry.numChildren = node.getChildCount();
265             entry.curChild = 0;
266             mCurViewStackEntry = entry;
267         }
268 
writeView(ViewNode child, Parcel out, PooledStringWriter pwriter, int levelAdj)269         void writeView(ViewNode child, Parcel out, PooledStringWriter pwriter, int levelAdj) {
270             if (DEBUG_PARCEL) Log.d(TAG, "write view: at " + out.dataPosition()
271                     + ", windows=" + mNumWrittenWindows
272                     + ", views=" + mNumWrittenViews
273                     + ", level=" + (mCurViewStackPos+levelAdj));
274             out.writeInt(VALIDATE_VIEW_TOKEN);
275             int flags = child.writeSelfToParcel(out, pwriter, mSanitizeOnWrite,
276                     mTmpMatrix, /*willWriteChildren=*/true);
277             mNumWrittenViews++;
278             // If the child has children, push it on the stack to write them next.
279             if ((flags&ViewNode.FLAGS_HAS_CHILDREN) != 0) {
280                 if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) Log.d(TAG,
281                         "Preparing to write " + child.mChildren.length
282                                 + " children: @ #" + mNumWrittenViews
283                                 + ", level " + (mCurViewStackPos+levelAdj));
284                 out.writeInt(child.mChildren.length);
285                 int pos = ++mCurViewStackPos;
286                 pushViewStackEntry(child, pos);
287             }
288         }
289 
writeNextEntryToParcel(AssistStructure as, Parcel out, PooledStringWriter pwriter)290         boolean writeNextEntryToParcel(AssistStructure as, Parcel out, PooledStringWriter pwriter) {
291             // Write next view node if appropriate.
292             if (mCurViewStackEntry != null) {
293                 if (mCurViewStackEntry.curChild < mCurViewStackEntry.numChildren) {
294                     // Write the next child in the current view.
295                     if (DEBUG_PARCEL_TREE) Log.d(TAG, "Writing child #"
296                             + mCurViewStackEntry.curChild + " in " + mCurViewStackEntry.node);
297                     ViewNode child = mCurViewStackEntry.node.mChildren[mCurViewStackEntry.curChild];
298                     mCurViewStackEntry.curChild++;
299                     writeView(child, out, pwriter, 1);
300                     return true;
301                 }
302 
303                 // We are done writing children of the current view; pop off the stack.
304                 do {
305                     int pos = --mCurViewStackPos;
306                     if (DEBUG_PARCEL_TREE) Log.d(TAG, "Done with " + mCurViewStackEntry.node
307                             + "; popping up to " + pos);
308                     if (pos < 0) {
309                         // Reached the last view; step to next window.
310                         if (DEBUG_PARCEL_TREE) Log.d(TAG, "Done with view hierarchy!");
311                         mCurViewStackEntry = null;
312                         break;
313                     }
314                     mCurViewStackEntry = mViewStack.get(pos);
315                 } while (mCurViewStackEntry.curChild >= mCurViewStackEntry.numChildren);
316                 return true;
317             }
318 
319             // Write the next window if appropriate.
320             int pos = mCurWindow;
321             if (pos < mNumWindows) {
322                 WindowNode win = as.mWindowNodes.get(pos);
323                 mCurWindow++;
324                 if (DEBUG_PARCEL) Log.d(TAG, "write window #" + pos + ": at " + out.dataPosition()
325                         + ", windows=" + mNumWrittenWindows
326                         + ", views=" + mNumWrittenViews);
327                 out.writeInt(VALIDATE_WINDOW_TOKEN);
328                 win.writeSelfToParcel(out, pwriter, mTmpMatrix);
329                 mNumWrittenWindows++;
330                 ViewNode root = win.mRoot;
331                 mCurViewStackPos = 0;
332                 if (DEBUG_PARCEL_TREE) Log.d(TAG, "Writing initial root view " + root);
333                 writeView(root, out, pwriter, 0);
334                 return true;
335             }
336 
337             return false;
338         }
339     }
340 
341     final class ParcelTransferReader {
342         final float[] mTmpMatrix = new float[9];
343         PooledStringReader mStringReader;
344 
345         int mNumReadWindows;
346         int mNumReadViews;
347 
348         private final IBinder mChannel;
349         private IBinder mTransferToken;
350         private Parcel mCurParcel;
351 
ParcelTransferReader(IBinder channel)352         ParcelTransferReader(IBinder channel) {
353             mChannel = channel;
354         }
355 
go()356         void go() {
357             fetchData();
358             mFlags = mCurParcel.readInt();
359             mAutofillFlags = mCurParcel.readInt();
360             mAcquisitionStartTime = mCurParcel.readLong();
361             mAcquisitionEndTime = mCurParcel.readLong();
362             final int N = mCurParcel.readInt();
363             if (N > 0) {
364                 if (DEBUG_PARCEL) Log.d(TAG, "Creating PooledStringReader @ "
365                         + mCurParcel.dataPosition());
366                 mStringReader = new PooledStringReader(mCurParcel);
367                 if (DEBUG_PARCEL) Log.d(TAG, "PooledStringReader size = "
368                         + mStringReader.getStringCount());
369                 for (int i=0; i<N; i++) {
370                     mWindowNodes.add(new WindowNode(this));
371                 }
372             }
373             if (DEBUG_PARCEL) Log.d(TAG, "Finished reading: at " + mCurParcel.dataPosition()
374                     + ", avail=" + mCurParcel.dataAvail() + ", windows=" + mNumReadWindows
375                     + ", views=" + mNumReadViews);
376             mCurParcel.recycle();
377             mCurParcel = null; // Parcel cannot be used after recycled.
378         }
379 
readParcel(int validateToken, int level)380         Parcel readParcel(int validateToken, int level) {
381             if (DEBUG_PARCEL) Log.d(TAG, "readParcel: at " + mCurParcel.dataPosition()
382                     + ", avail=" + mCurParcel.dataAvail() + ", windows=" + mNumReadWindows
383                     + ", views=" + mNumReadViews + ", level=" + level);
384             int token = mCurParcel.readInt();
385             if (token != 0) {
386                 if (token != validateToken) {
387                     throw new BadParcelableException("Got token " + Integer.toHexString(token)
388                             + ", expected token " + Integer.toHexString(validateToken));
389                 }
390                 return mCurParcel;
391             }
392             // We have run out of partial data, need to read another batch.
393             mTransferToken = mCurParcel.readStrongBinder();
394             if (mTransferToken == null) {
395                 throw new IllegalStateException(
396                         "Reached end of partial data without transfer token");
397             }
398             if (DEBUG_PARCEL) Log.d(TAG, "Ran out of partial data at "
399                     + mCurParcel.dataPosition() + ", token " + mTransferToken);
400             fetchData();
401             if (DEBUG_PARCEL) Log.d(TAG, "Creating PooledStringReader @ "
402                     + mCurParcel.dataPosition());
403             mStringReader = new PooledStringReader(mCurParcel);
404             if (DEBUG_PARCEL) Log.d(TAG, "PooledStringReader size = "
405                     + mStringReader.getStringCount());
406             if (DEBUG_PARCEL) Log.d(TAG, "readParcel: at " + mCurParcel.dataPosition()
407                     + ", avail=" + mCurParcel.dataAvail() + ", windows=" + mNumReadWindows
408                     + ", views=" + mNumReadViews);
409             mCurParcel.readInt();
410             return mCurParcel;
411         }
412 
fetchData()413         private void fetchData() {
414             Parcel data = Parcel.obtain();
415             try {
416                 data.writeInterfaceToken(DESCRIPTOR);
417                 data.writeStrongBinder(mTransferToken);
418                 if (DEBUG_PARCEL) Log.d(TAG, "Requesting data with token " + mTransferToken);
419                 if (mCurParcel != null) {
420                     mCurParcel.recycle();
421                 }
422                 mCurParcel = Parcel.obtain();
423                 try {
424                     mChannel.transact(TRANSACTION_XFER, data, mCurParcel, 0);
425                 } catch (RemoteException e) {
426                     Log.w(TAG, "Failure reading AssistStructure data", e);
427                     throw new IllegalStateException("Failure reading AssistStructure data: " + e);
428                 }
429             } finally {
430                 data.recycle();
431             }
432             mNumReadWindows = mNumReadViews = 0;
433         }
434     }
435 
436     final static class ViewNodeText {
437         CharSequence mText;
438         float mTextSize;
439         int mTextStyle;
440         int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED;
441         int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED;
442         int mTextSelectionStart;
443         int mTextSelectionEnd;
444         int[] mLineCharOffsets;
445         int[] mLineBaselines;
446         String mHint;
447 
ViewNodeText()448         ViewNodeText() {
449         }
450 
isSimple()451         boolean isSimple() {
452             return mTextBackgroundColor == ViewNode.TEXT_COLOR_UNDEFINED
453                     && mTextSelectionStart == 0 && mTextSelectionEnd == 0
454                     && mLineCharOffsets == null && mLineBaselines == null && mHint == null;
455         }
456 
ViewNodeText(Parcel in, boolean simple)457         ViewNodeText(Parcel in, boolean simple) {
458             mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
459             mTextSize = in.readFloat();
460             mTextStyle = in.readInt();
461             mTextColor = in.readInt();
462             if (!simple) {
463                 mTextBackgroundColor = in.readInt();
464                 mTextSelectionStart = in.readInt();
465                 mTextSelectionEnd = in.readInt();
466                 mLineCharOffsets = in.createIntArray();
467                 mLineBaselines = in.createIntArray();
468                 mHint = in.readString();
469             }
470         }
471 
writeToParcel(Parcel out, boolean simple, boolean writeSensitive)472         void writeToParcel(Parcel out, boolean simple, boolean writeSensitive) {
473             TextUtils.writeToParcel(writeSensitive ? mText : "", out, 0);
474             out.writeFloat(mTextSize);
475             out.writeInt(mTextStyle);
476             out.writeInt(mTextColor);
477             if (!simple) {
478                 out.writeInt(mTextBackgroundColor);
479                 out.writeInt(mTextSelectionStart);
480                 out.writeInt(mTextSelectionEnd);
481                 out.writeIntArray(mLineCharOffsets);
482                 out.writeIntArray(mLineBaselines);
483                 out.writeString(mHint);
484             }
485         }
486     }
487 
488     /**
489      * Describes a window in the assist data.
490      */
491     static public class WindowNode {
492         final int mX;
493         final int mY;
494         final int mWidth;
495         final int mHeight;
496         final CharSequence mTitle;
497         final int mDisplayId;
498         final ViewNode mRoot;
499 
WindowNode(AssistStructure assist, ViewRootImpl root, boolean forAutoFill, int flags)500         WindowNode(AssistStructure assist, ViewRootImpl root, boolean forAutoFill, int flags) {
501             View view = root.getView();
502             Rect rect = new Rect();
503             view.getBoundsOnScreen(rect);
504             mX = rect.left - view.getLeft();
505             mY = rect.top - view.getTop();
506             mWidth = rect.width();
507             mHeight = rect.height();
508             mTitle = root.getTitle();
509             mDisplayId = root.getDisplayId();
510             mRoot = new ViewNode();
511 
512             ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
513             if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
514                 if (forAutoFill) {
515                     final int viewFlags = resolveViewAutofillFlags(view.getContext(), flags);
516                     view.onProvideAutofillStructure(builder, viewFlags);
517                 } else {
518                     // This is a secure window, so it doesn't want a screenshot, and that
519                     // means we should also not copy out its view hierarchy for Assist
520                     view.onProvideStructure(builder);
521                     builder.setAssistBlocked(true);
522                     return;
523                 }
524             }
525             if (forAutoFill) {
526                 final int viewFlags = resolveViewAutofillFlags(view.getContext(), flags);
527                 view.dispatchProvideAutofillStructure(builder, viewFlags);
528             } else {
529                 view.dispatchProvideStructure(builder);
530             }
531         }
532 
WindowNode(ParcelTransferReader reader)533         WindowNode(ParcelTransferReader reader) {
534             Parcel in = reader.readParcel(VALIDATE_WINDOW_TOKEN, 0);
535             reader.mNumReadWindows++;
536             mX = in.readInt();
537             mY = in.readInt();
538             mWidth = in.readInt();
539             mHeight = in.readInt();
540             mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
541             mDisplayId = in.readInt();
542             mRoot = new ViewNode(reader, 0);
543         }
544 
resolveViewAutofillFlags(Context context, int fillRequestFlags)545         int resolveViewAutofillFlags(Context context, int fillRequestFlags) {
546             return (fillRequestFlags & FillRequest.FLAG_MANUAL_REQUEST) != 0
547                         || context.isAutofillCompatibilityEnabled()
548                     ? View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0;
549         }
550 
writeSelfToParcel(Parcel out, PooledStringWriter pwriter, float[] tmpMatrix)551         void writeSelfToParcel(Parcel out, PooledStringWriter pwriter, float[] tmpMatrix) {
552             out.writeInt(mX);
553             out.writeInt(mY);
554             out.writeInt(mWidth);
555             out.writeInt(mHeight);
556             TextUtils.writeToParcel(mTitle, out, 0);
557             out.writeInt(mDisplayId);
558         }
559 
560         /**
561          * Returns the left edge of the window, in pixels, relative to the left
562          * edge of the screen.
563          */
getLeft()564         public int getLeft() {
565             return mX;
566         }
567 
568         /**
569          * Returns the top edge of the window, in pixels, relative to the top
570          * edge of the screen.
571          */
getTop()572         public int getTop() {
573             return mY;
574         }
575 
576         /**
577          * Returns the total width of the window in pixels.
578          */
getWidth()579         public int getWidth() {
580             return mWidth;
581         }
582 
583         /**
584          * Returns the total height of the window in pixels.
585          */
getHeight()586         public int getHeight() {
587             return mHeight;
588         }
589 
590         /**
591          * Returns the title associated with the window, if it has one.
592          */
getTitle()593         public CharSequence getTitle() {
594             return mTitle;
595         }
596 
597         /**
598          * Returns the ID of the display this window is on, for use with
599          * {@link android.hardware.display.DisplayManager#getDisplay DisplayManager.getDisplay()}.
600          */
getDisplayId()601         public int getDisplayId() {
602             return mDisplayId;
603         }
604 
605         /**
606          * Returns the {@link ViewNode} containing the root content of the window.
607          */
getRootViewNode()608         public ViewNode getRootViewNode() {
609             return mRoot;
610         }
611     }
612 
613     /**
614      * Describes a single view in the assist data.
615      */
616     static public class ViewNode {
617         /**
618          * Magic value for text color that has not been defined, which is very unlikely
619          * to be confused with a real text color.
620          */
621         public static final int TEXT_COLOR_UNDEFINED = 1;
622 
623         public static final int TEXT_STYLE_BOLD = 1<<0;
624         public static final int TEXT_STYLE_ITALIC = 1<<1;
625         public static final int TEXT_STYLE_UNDERLINE = 1<<2;
626         public static final int TEXT_STYLE_STRIKE_THRU = 1<<3;
627 
628         int mId = View.NO_ID;
629         String mIdPackage;
630         String mIdType;
631         String mIdEntry;
632 
633         AutofillId mAutofillId;
634         @View.AutofillType int mAutofillType = View.AUTOFILL_TYPE_NONE;
635         @Nullable String[] mAutofillHints;
636         AutofillValue mAutofillValue;
637         CharSequence[] mAutofillOptions;
638         boolean mSanitized;
639         HtmlInfo mHtmlInfo;
640         int mMinEms = -1;
641         int mMaxEms = -1;
642         int mMaxLength = -1;
643         @Nullable String mTextIdEntry;
644         @Nullable String mHintIdEntry;
645         @AutofillImportance int mImportantForAutofill;
646 
647         // POJO used to override some autofill-related values when the node is parcelized.
648         // Not written to parcel.
649         AutofillOverlay mAutofillOverlay;
650 
651         int mX;
652         int mY;
653         int mScrollX;
654         int mScrollY;
655         int mWidth;
656         int mHeight;
657         Matrix mMatrix;
658         float mElevation;
659         float mAlpha = 1.0f;
660 
661         static final int FLAGS_DISABLED = 0x00000001;
662         static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
663         static final int FLAGS_FOCUSABLE = 0x00000010;
664         static final int FLAGS_FOCUSED = 0x00000020;
665         static final int FLAGS_SELECTED = 0x00000040;
666         static final int FLAGS_ASSIST_BLOCKED = 0x00000080;
667         static final int FLAGS_CHECKABLE = 0x00000100;
668         static final int FLAGS_CHECKED = 0x00000200;
669         static final int FLAGS_CLICKABLE = 0x00000400;
670         static final int FLAGS_LONG_CLICKABLE = 0x00000800;
671         static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x00001000;
672         static final int FLAGS_ACTIVATED = 0x00002000;
673         static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000;
674         static final int FLAGS_OPAQUE = 0x00008000;
675 
676         static final int FLAGS_HAS_MIME_TYPES = 0x80000000;
677         static final int FLAGS_HAS_MATRIX = 0x40000000;
678         static final int FLAGS_HAS_ALPHA = 0x20000000;
679         static final int FLAGS_HAS_ELEVATION = 0x10000000;
680         static final int FLAGS_HAS_SCROLL = 0x08000000;
681         static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
682         static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
683         static final int FLAGS_HAS_TEXT = 0x01000000;
684         static final int FLAGS_HAS_COMPLEX_TEXT = 0x00800000;
685         static final int FLAGS_HAS_EXTRAS = 0x00400000;
686         static final int FLAGS_HAS_ID = 0x00200000;
687         static final int FLAGS_HAS_CHILDREN = 0x00100000;
688         static final int FLAGS_HAS_URL_DOMAIN = 0x00080000;
689         static final int FLAGS_HAS_INPUT_TYPE = 0x00040000;
690         static final int FLAGS_HAS_URL_SCHEME = 0x00020000;
691         static final int FLAGS_HAS_LOCALE_LIST = 0x00010000;
692         static final int FLAGS_ALL_CONTROL = 0xfff00000;
693 
694         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID =         0x0001;
695         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID = 0x0002;
696         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE =           0x0004;
697         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE =            0x0008;
698         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS =           0x0010;
699         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS =         0x0020;
700         static final int AUTOFILL_FLAGS_HAS_HTML_INFO =                0x0040;
701         static final int AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY =            0x0080;
702         static final int AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS =             0x0100;
703         static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS =             0x0200;
704         static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH =          0x0400;
705         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID =      0x0800;
706         static final int AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY =            0x1000;
707 
708         int mFlags;
709         int mAutofillFlags;
710 
711         String mClassName;
712         CharSequence mContentDescription;
713 
714         ViewNodeText mText;
715         int mInputType;
716         String mWebScheme;
717         String mWebDomain;
718         Bundle mExtras;
719         LocaleList mLocaleList;
720         String[] mReceiveContentMimeTypes;
721 
722         ViewNode[] mChildren;
723 
724         // TODO(b/111276913): temporarily made public / @hide until we decide what will be used by
725         // COntent Capture.
726         /** @hide */
727         @SystemApi
ViewNode()728         public ViewNode() {
729         }
730 
ViewNode(@onNull Parcel in)731         ViewNode(@NonNull Parcel in) {
732             initializeFromParcelWithoutChildren(in, /*preader=*/null, /*tmpMatrix=*/null);
733         }
734 
ViewNode(ParcelTransferReader reader, int nestingLevel)735         ViewNode(ParcelTransferReader reader, int nestingLevel) {
736             final Parcel in = reader.readParcel(VALIDATE_VIEW_TOKEN, nestingLevel);
737             reader.mNumReadViews++;
738             initializeFromParcelWithoutChildren(in, Objects.requireNonNull(reader.mStringReader),
739                     Objects.requireNonNull(reader.mTmpMatrix));
740             if ((mFlags & FLAGS_HAS_CHILDREN) != 0) {
741                 final int numChildren = in.readInt();
742                 if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) {
743                     Log.d(TAG,
744                             "Preparing to read " + numChildren
745                                     + " children: @ #" + reader.mNumReadViews
746                                     + ", level " + nestingLevel);
747                 }
748                 mChildren = new ViewNode[numChildren];
749                 for (int i = 0; i < numChildren; i++) {
750                     mChildren[i] = new ViewNode(reader, nestingLevel + 1);
751                 }
752             }
753         }
754 
writeString(@onNull Parcel out, @Nullable PooledStringWriter pwriter, @Nullable String str)755         private static void writeString(@NonNull Parcel out, @Nullable PooledStringWriter pwriter,
756                 @Nullable String str) {
757             if (pwriter != null) {
758                 pwriter.writeString(str);
759             } else {
760                 out.writeString(str);
761             }
762         }
763 
764         @Nullable
readString(@onNull Parcel in, @Nullable PooledStringReader preader)765         private static String readString(@NonNull Parcel in, @Nullable PooledStringReader preader) {
766             if (preader != null) {
767                 return preader.readString();
768             }
769             return in.readString();
770         }
771 
772         // This does not read the child nodes.
initializeFromParcelWithoutChildren(Parcel in, @Nullable PooledStringReader preader, @Nullable float[] tmpMatrix)773         void initializeFromParcelWithoutChildren(Parcel in, @Nullable PooledStringReader preader,
774                 @Nullable float[] tmpMatrix) {
775             mClassName = readString(in, preader);
776             mFlags = in.readInt();
777             final int flags = mFlags;
778             mAutofillFlags = in.readInt();
779             final int autofillFlags = mAutofillFlags;
780             if ((flags&FLAGS_HAS_ID) != 0) {
781                 mId = in.readInt();
782                 if (mId != View.NO_ID) {
783                     mIdEntry = readString(in, preader);
784                     if (mIdEntry != null) {
785                         mIdType = readString(in, preader);
786                         mIdPackage = readString(in, preader);
787                     }
788                 }
789             }
790 
791             if (autofillFlags != 0) {
792                 mSanitized = in.readInt() == 1;
793                 mImportantForAutofill = in.readInt();
794 
795                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID) != 0) {
796                     int autofillViewId = in.readInt();
797                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID) != 0) {
798                         mAutofillId = new AutofillId(autofillViewId, in.readInt());
799                     } else {
800                         mAutofillId = new AutofillId(autofillViewId);
801                     }
802                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID) != 0) {
803                         mAutofillId.setSessionId(in.readInt());
804                     }
805                 }
806                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
807                     mAutofillType = in.readInt();
808                 }
809                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS) != 0) {
810                     mAutofillHints = in.readStringArray();
811                 }
812                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE) != 0) {
813                     mAutofillValue = in.readParcelable(null);
814                 }
815                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
816                     mAutofillOptions = in.readCharSequenceArray();
817                 }
818                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HTML_INFO) != 0) {
819                     mHtmlInfo = in.readParcelable(null);
820                 }
821                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS) != 0) {
822                     mMinEms = in.readInt();
823                 }
824                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS) != 0) {
825                     mMaxEms = in.readInt();
826                 }
827                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
828                     mMaxLength = in.readInt();
829                 }
830                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
831                     mTextIdEntry = readString(in, preader);
832                 }
833                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY) != 0) {
834                     mHintIdEntry = readString(in, preader);
835                 }
836             }
837             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
838                 mX = in.readInt();
839                 mY = in.readInt();
840                 mWidth = in.readInt();
841                 mHeight = in.readInt();
842             } else {
843                 int val = in.readInt();
844                 mX = val&0x7fff;
845                 mY = (val>>16)&0x7fff;
846                 val = in.readInt();
847                 mWidth = val&0x7fff;
848                 mHeight = (val>>16)&0x7fff;
849             }
850             if ((flags&FLAGS_HAS_SCROLL) != 0) {
851                 mScrollX = in.readInt();
852                 mScrollY = in.readInt();
853             }
854             if ((flags&FLAGS_HAS_MATRIX) != 0) {
855                 mMatrix = new Matrix();
856                 if (tmpMatrix == null) {
857                     tmpMatrix = new float[9];
858                 }
859                 in.readFloatArray(tmpMatrix);
860                 mMatrix.setValues(tmpMatrix);
861             }
862             if ((flags&FLAGS_HAS_ELEVATION) != 0) {
863                 mElevation = in.readFloat();
864             }
865             if ((flags&FLAGS_HAS_ALPHA) != 0) {
866                 mAlpha = in.readFloat();
867             }
868             if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
869                 mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
870             }
871             if ((flags&FLAGS_HAS_TEXT) != 0) {
872                 mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
873             }
874             if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
875                 mInputType = in.readInt();
876             }
877             if ((flags&FLAGS_HAS_URL_SCHEME) != 0) {
878                 mWebScheme = in.readString();
879             }
880             if ((flags&FLAGS_HAS_URL_DOMAIN) != 0) {
881                 mWebDomain = in.readString();
882             }
883             if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) {
884                 mLocaleList = in.readParcelable(null);
885             }
886             if ((flags & FLAGS_HAS_MIME_TYPES) != 0) {
887                 mReceiveContentMimeTypes = in.readStringArray();
888             }
889             if ((flags&FLAGS_HAS_EXTRAS) != 0) {
890                 mExtras = in.readBundle();
891             }
892         }
893 
894         /**
895          * This does not write the child nodes.
896          *
897          * @param willWriteChildren whether child nodes will be written to the parcel or not after
898          *                          calling this method.
899          */
writeSelfToParcel(@onNull Parcel out, @Nullable PooledStringWriter pwriter, boolean sanitizeOnWrite, @Nullable float[] tmpMatrix, boolean willWriteChildren)900         int writeSelfToParcel(@NonNull Parcel out, @Nullable PooledStringWriter pwriter,
901                 boolean sanitizeOnWrite, @Nullable float[] tmpMatrix, boolean willWriteChildren) {
902             // Guard used to skip non-sanitized data when writing for autofill.
903             boolean writeSensitive = true;
904 
905             int flags = mFlags & ~FLAGS_ALL_CONTROL;
906             int autofillFlags = 0;
907 
908             if (mId != View.NO_ID) {
909                 flags |= FLAGS_HAS_ID;
910             }
911             if ((mX&~0x7fff) != 0 || (mY&~0x7fff) != 0
912                     || (mWidth&~0x7fff) != 0 | (mHeight&~0x7fff) != 0) {
913                 flags |= FLAGS_HAS_LARGE_COORDS;
914             }
915             if (mScrollX != 0 || mScrollY != 0) {
916                 flags |= FLAGS_HAS_SCROLL;
917             }
918             if (mMatrix != null) {
919                 flags |= FLAGS_HAS_MATRIX;
920             }
921             if (mElevation != 0) {
922                 flags |= FLAGS_HAS_ELEVATION;
923             }
924             if (mAlpha != 1.0f) {
925                 flags |= FLAGS_HAS_ALPHA;
926             }
927             if (mContentDescription != null) {
928                 flags |= FLAGS_HAS_CONTENT_DESCRIPTION;
929             }
930             if (mText != null) {
931                 flags |= FLAGS_HAS_TEXT;
932                 if (!mText.isSimple()) {
933                     flags |= FLAGS_HAS_COMPLEX_TEXT;
934                 }
935             }
936             if (mInputType != 0) {
937                 flags |= FLAGS_HAS_INPUT_TYPE;
938             }
939             if (mWebScheme != null) {
940                 flags |= FLAGS_HAS_URL_SCHEME;
941             }
942             if (mWebDomain != null) {
943                 flags |= FLAGS_HAS_URL_DOMAIN;
944             }
945             if (mLocaleList != null) {
946                 flags |= FLAGS_HAS_LOCALE_LIST;
947             }
948             if (mReceiveContentMimeTypes != null) {
949                 flags |= FLAGS_HAS_MIME_TYPES;
950             }
951             if (mExtras != null) {
952                 flags |= FLAGS_HAS_EXTRAS;
953             }
954             if (mChildren != null && willWriteChildren) {
955                 flags |= FLAGS_HAS_CHILDREN;
956             }
957             if (mAutofillId != null) {
958                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID;
959                 if (mAutofillId.isVirtualInt()) {
960                     autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID;
961                 }
962                 if (mAutofillId.hasSession()) {
963                     autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID;
964                 }
965             }
966             if (mAutofillValue != null) {
967                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE;
968             }
969             if (mAutofillType != View.AUTOFILL_TYPE_NONE) {
970                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE;
971             }
972             if (mAutofillHints != null) {
973                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS;
974             }
975             if (mAutofillOptions != null) {
976                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS;
977             }
978             if (mHtmlInfo instanceof Parcelable) {
979                 autofillFlags |= AUTOFILL_FLAGS_HAS_HTML_INFO;
980             }
981             if (mMinEms > -1) {
982                 autofillFlags |= AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS;
983             }
984             if (mMaxEms > -1) {
985                 autofillFlags |= AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS;
986             }
987             if (mMaxLength > -1) {
988                 autofillFlags |= AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH;
989             }
990             if (mTextIdEntry != null) {
991                 autofillFlags |= AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY;
992             }
993             if (mHintIdEntry != null) {
994                 autofillFlags |= AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY;
995             }
996 
997             writeString(out, pwriter, mClassName);
998 
999             int writtenFlags = flags;
1000             if (autofillFlags != 0 && (mSanitized || !sanitizeOnWrite)) {
1001                 // Remove 'checked' from sanitized autofill request.
1002                 writtenFlags = flags & ~FLAGS_CHECKED;
1003             }
1004             if (mAutofillOverlay != null) {
1005                 if (mAutofillOverlay.focused) {
1006                     writtenFlags |= ViewNode.FLAGS_FOCUSED;
1007                 } else {
1008                     writtenFlags &= ~ViewNode.FLAGS_FOCUSED;
1009                 }
1010             }
1011 
1012             out.writeInt(writtenFlags);
1013             out.writeInt(autofillFlags);
1014             if ((flags&FLAGS_HAS_ID) != 0) {
1015                 out.writeInt(mId);
1016                 if (mId != View.NO_ID) {
1017                     writeString(out, pwriter, mIdEntry);
1018                     if (mIdEntry != null) {
1019                         writeString(out, pwriter, mIdType);
1020                         writeString(out, pwriter, mIdPackage);
1021                     }
1022                 }
1023             }
1024 
1025             if (autofillFlags != 0) {
1026                 out.writeInt(mSanitized ? 1 : 0);
1027                 out.writeInt(mImportantForAutofill);
1028                 writeSensitive = mSanitized || !sanitizeOnWrite;
1029                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID) != 0) {
1030                     out.writeInt(mAutofillId.getViewId());
1031                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID) != 0) {
1032                         out.writeInt(mAutofillId.getVirtualChildIntId());
1033                     }
1034                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID) != 0) {
1035                         out.writeInt(mAutofillId.getSessionId());
1036                     }
1037                 }
1038                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
1039                     out.writeInt(mAutofillType);
1040                 }
1041                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS) != 0) {
1042                     out.writeStringArray(mAutofillHints);
1043                 }
1044                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE) != 0) {
1045                     final AutofillValue sanitizedValue;
1046                     if (writeSensitive) {
1047                         sanitizedValue = mAutofillValue;
1048                     } else if (mAutofillOverlay != null && mAutofillOverlay.value != null) {
1049                         sanitizedValue = mAutofillOverlay.value;
1050                     } else {
1051                         sanitizedValue = null;
1052                     }
1053                     out.writeParcelable(sanitizedValue, 0);
1054                 }
1055                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
1056                     out.writeCharSequenceArray(mAutofillOptions);
1057                 }
1058                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HTML_INFO) != 0) {
1059                     out.writeParcelable((Parcelable) mHtmlInfo, 0);
1060                 }
1061                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS) != 0) {
1062                     out.writeInt(mMinEms);
1063                 }
1064                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS) != 0) {
1065                     out.writeInt(mMaxEms);
1066                 }
1067                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
1068                     out.writeInt(mMaxLength);
1069                 }
1070                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
1071                     writeString(out, pwriter, mTextIdEntry);
1072                 }
1073                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY) != 0) {
1074                     writeString(out, pwriter, mHintIdEntry);
1075                 }
1076             }
1077             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
1078                 out.writeInt(mX);
1079                 out.writeInt(mY);
1080                 out.writeInt(mWidth);
1081                 out.writeInt(mHeight);
1082             } else {
1083                 out.writeInt((mY<<16) | mX);
1084                 out.writeInt((mHeight<<16) | mWidth);
1085             }
1086             if ((flags&FLAGS_HAS_SCROLL) != 0) {
1087                 out.writeInt(mScrollX);
1088                 out.writeInt(mScrollY);
1089             }
1090             if ((flags&FLAGS_HAS_MATRIX) != 0) {
1091                 if (tmpMatrix == null) {
1092                     tmpMatrix = new float[9];
1093                 }
1094                 mMatrix.getValues(tmpMatrix);
1095                 out.writeFloatArray(tmpMatrix);
1096             }
1097             if ((flags&FLAGS_HAS_ELEVATION) != 0) {
1098                 out.writeFloat(mElevation);
1099             }
1100             if ((flags&FLAGS_HAS_ALPHA) != 0) {
1101                 out.writeFloat(mAlpha);
1102             }
1103             if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
1104                 TextUtils.writeToParcel(mContentDescription, out, 0);
1105             }
1106             if ((flags&FLAGS_HAS_TEXT) != 0) {
1107                 mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0, writeSensitive);
1108             }
1109             if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
1110                 out.writeInt(mInputType);
1111             }
1112             if ((flags & FLAGS_HAS_URL_SCHEME) != 0) {
1113                 out.writeString(mWebScheme);
1114             }
1115             if ((flags&FLAGS_HAS_URL_DOMAIN) != 0) {
1116                 out.writeString(mWebDomain);
1117             }
1118             if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) {
1119                 out.writeParcelable(mLocaleList, 0);
1120             }
1121             if ((flags & FLAGS_HAS_MIME_TYPES) != 0) {
1122                 out.writeStringArray(mReceiveContentMimeTypes);
1123             }
1124             if ((flags&FLAGS_HAS_EXTRAS) != 0) {
1125                 out.writeBundle(mExtras);
1126             }
1127             return flags;
1128         }
1129 
1130         /**
1131          * Returns the ID associated with this view, as per {@link View#getId() View.getId()}.
1132          */
getId()1133         public int getId() {
1134             return mId;
1135         }
1136 
1137         /**
1138          * If {@link #getId()} is a resource identifier, this is the package name of that
1139          * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
1140          * for more information.
1141          */
1142         @Nullable
getIdPackage()1143         public String getIdPackage() {
1144             return mIdPackage;
1145         }
1146 
1147         /**
1148          * If {@link #getId()} is a resource identifier, this is the type name of that
1149          * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
1150          * for more information.
1151          */
1152         @Nullable
getIdType()1153         public String getIdType() {
1154             return mIdType;
1155         }
1156 
1157         /**
1158          * If {@link #getId()} is a resource identifier, this is the entry name of that
1159          * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
1160          * for more information.
1161          */
1162         @Nullable
getIdEntry()1163         public String getIdEntry() {
1164             return mIdEntry;
1165         }
1166 
1167         /**
1168          * Gets the id that can be used to autofill the view contents.
1169          *
1170          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
1171          *
1172          * @return id that can be used to autofill the view contents, or {@code null} if the
1173          * structure was created for assist purposes.
1174          */
getAutofillId()1175         @Nullable public AutofillId getAutofillId() {
1176             return mAutofillId;
1177         }
1178 
1179         /**
1180          * Gets the type of value that can be used to autofill the view contents.
1181          *
1182          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
1183          *
1184          * @return autofill type as defined by {@link View#getAutofillType()},
1185          * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for assist purposes.
1186          */
getAutofillType()1187         public @View.AutofillType int getAutofillType() {
1188             return mAutofillType;
1189         }
1190 
1191         /**
1192          * Describes the content of a view so that a autofill service can fill in the appropriate
1193          * data.
1194          *
1195          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1196          * not for Assist - see {@link View#getAutofillHints()} for more info.
1197          *
1198          * @return The autofill hints for this view, or {@code null} if the structure was created
1199          * for assist purposes.
1200          */
getAutofillHints()1201         @Nullable public String[] getAutofillHints() {
1202             return mAutofillHints;
1203         }
1204 
1205         /**
1206          * Gets the value of this view.
1207          *
1208          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1209          * not for assist purposes.
1210          *
1211          * @return the autofill value of this view, or {@code null} if the structure was created
1212          * for assist purposes.
1213          */
getAutofillValue()1214         @Nullable public AutofillValue getAutofillValue() {
1215             return mAutofillValue;
1216         }
1217 
1218         /** @hide **/
setAutofillOverlay(AutofillOverlay overlay)1219         public void setAutofillOverlay(AutofillOverlay overlay) {
1220             mAutofillOverlay = overlay;
1221         }
1222 
1223         /**
1224          * Gets the options that can be used to autofill this view.
1225          *
1226          * <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate
1227          * the meaning of each possible value in the list.
1228          *
1229          * <p>It's relevant when the {@link AssistStructure} is used for autofill purposes, not
1230          * for assist purposes.
1231          *
1232          * @return the options that can be used to autofill this view, or {@code null} if the
1233          * structure was created for assist purposes.
1234          */
getAutofillOptions()1235         @Nullable public CharSequence[] getAutofillOptions() {
1236             return mAutofillOptions;
1237         }
1238 
1239         /**
1240          * Gets the {@link android.text.InputType} bits of this structure.
1241          *
1242          * @return bits as defined by {@link android.text.InputType}.
1243          */
getInputType()1244         public int getInputType() {
1245             return mInputType;
1246         }
1247 
1248         /** @hide */
isSanitized()1249         public boolean isSanitized() {
1250             return mSanitized;
1251         }
1252 
1253         /**
1254          * Updates the {@link AutofillValue} of this structure.
1255          *
1256          * <p>Should be used just before sending the structure to the
1257          * {@link android.service.autofill.AutofillService} for saving, since it will override the
1258          * initial value.
1259          *
1260          * @hide
1261          */
updateAutofillValue(AutofillValue value)1262         public void updateAutofillValue(AutofillValue value) {
1263             mAutofillValue = value;
1264             if (value.isText()) {
1265                 if (mText == null) {
1266                     mText = new ViewNodeText();
1267                 }
1268                 mText.mText = value.getTextValue();
1269             }
1270         }
1271 
1272         /**
1273          * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
1274          */
getLeft()1275         public int getLeft() {
1276             return mX;
1277         }
1278 
1279         /**
1280          * Returns the top edge of this view, in pixels, relative to the top edge of its parent.
1281          */
getTop()1282         public int getTop() {
1283             return mY;
1284         }
1285 
1286         /**
1287          * Returns the current X scroll offset of this view, as per
1288          * {@link android.view.View#getScrollX() View.getScrollX()}.
1289          */
getScrollX()1290         public int getScrollX() {
1291             return mScrollX;
1292         }
1293 
1294         /**
1295          * Returns the current Y scroll offset of this view, as per
1296          * {@link android.view.View#getScrollX() View.getScrollY()}.
1297          */
getScrollY()1298         public int getScrollY() {
1299             return mScrollY;
1300         }
1301 
1302         /**
1303          * Returns the width of this view, in pixels.
1304          */
getWidth()1305         public int getWidth() {
1306             return mWidth;
1307         }
1308 
1309         /**
1310          * Returns the height of this view, in pixels.
1311          */
getHeight()1312         public int getHeight() {
1313             return mHeight;
1314         }
1315 
1316         /**
1317          * Returns the transformation that has been applied to this view, such as a translation
1318          * or scaling.  The returned Matrix object is owned by ViewNode; do not modify it.
1319          * Returns null if there is no transformation applied to the view.
1320          *
1321          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1322          * not for autofill purposes.
1323          */
getTransformation()1324         public Matrix getTransformation() {
1325             return mMatrix;
1326         }
1327 
1328         /**
1329          * Returns the visual elevation of the view, used for shadowing and other visual
1330          * characterstics, as set by {@link ViewStructure#setElevation
1331          * ViewStructure.setElevation(float)}.
1332          *
1333          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1334          * not for autofill purposes.
1335          */
getElevation()1336         public float getElevation() {
1337             return mElevation;
1338         }
1339 
1340         /**
1341          * Returns the alpha transformation of the view, used to reduce the overall opacity
1342          * of the view's contents, as set by {@link ViewStructure#setAlpha
1343          * ViewStructure.setAlpha(float)}.
1344          *
1345          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1346          * not for autofill purposes.
1347          */
getAlpha()1348         public float getAlpha() {
1349             return mAlpha;
1350         }
1351 
1352         /**
1353          * Returns the visibility mode of this view, as per
1354          * {@link android.view.View#getVisibility() View.getVisibility()}.
1355          */
getVisibility()1356         public int getVisibility() {
1357             return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
1358         }
1359 
1360         /**
1361          * Returns true if assist data has been blocked starting at this node in the hierarchy.
1362          */
isAssistBlocked()1363         public boolean isAssistBlocked() {
1364             return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) != 0;
1365         }
1366 
1367         /**
1368          * Returns true if this node is in an enabled state.
1369          */
isEnabled()1370         public boolean isEnabled() {
1371             return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
1372         }
1373 
1374         /**
1375          * Returns true if this node is clickable by the user.
1376          */
isClickable()1377         public boolean isClickable() {
1378             return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
1379         }
1380 
1381         /**
1382          * Returns true if this node can take input focus.
1383          */
isFocusable()1384         public boolean isFocusable() {
1385             return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
1386         }
1387 
1388         /**
1389          * Returns true if this node currently had input focus at the time that the
1390          * structure was collected.
1391          */
isFocused()1392         public boolean isFocused() {
1393             return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
1394         }
1395 
1396         /**
1397          * Returns true if this node currently had accessibility focus at the time that the
1398          * structure was collected.
1399          */
isAccessibilityFocused()1400         public boolean isAccessibilityFocused() {
1401             return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
1402         }
1403 
1404         /**
1405          * Returns true if this node represents something that is checkable by the user.
1406          */
isCheckable()1407         public boolean isCheckable() {
1408             return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
1409         }
1410 
1411         /**
1412          * Returns true if this node is currently in a checked state.
1413          */
isChecked()1414         public boolean isChecked() {
1415             return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
1416         }
1417 
1418         /**
1419          * Returns true if this node has currently been selected by the user.
1420          */
isSelected()1421         public boolean isSelected() {
1422             return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
1423         }
1424 
1425         /**
1426          * Returns true if this node has currently been activated by the user.
1427          */
isActivated()1428         public boolean isActivated() {
1429             return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
1430         }
1431 
1432         /**
1433          * Returns true if this node is opaque.
1434          */
isOpaque()1435         public boolean isOpaque() { return (mFlags&ViewNode.FLAGS_OPAQUE) != 0; }
1436 
1437         /**
1438          * Returns true if this node is something the user can perform a long click/press on.
1439          */
isLongClickable()1440         public boolean isLongClickable() {
1441             return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
1442         }
1443 
1444         /**
1445          * Returns true if this node is something the user can perform a context click on.
1446          */
isContextClickable()1447         public boolean isContextClickable() {
1448             return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
1449         }
1450 
1451         /**
1452          * Returns the class name of the node's implementation, indicating its behavior.
1453          * For example, a button will report "android.widget.Button" meaning it behaves
1454          * like a {@link android.widget.Button}.
1455          */
1456         @Nullable
getClassName()1457         public String getClassName() {
1458             return mClassName;
1459         }
1460 
1461         /**
1462          * Returns any content description associated with the node, which semantically describes
1463          * its purpose for accessibility and other uses.
1464          */
1465         @Nullable
getContentDescription()1466         public CharSequence getContentDescription() {
1467             return mContentDescription;
1468         }
1469 
1470         /**
1471          * Returns the domain of the HTML document represented by this view.
1472          *
1473          * <p>Typically used when the view associated with the view is a container for an HTML
1474          * document.
1475          *
1476          * <p><b>Warning:</b> an autofill service cannot trust the value reported by this method
1477          * without verifing its authenticity&mdash;see the "Web security" section of
1478          * {@link android.service.autofill.AutofillService} for more details.
1479          *
1480          * @return domain-only part of the document. For example, if the full URL is
1481          * {@code https://example.com/login?user=my_user}, it returns {@code example.com}.
1482          */
getWebDomain()1483         @Nullable public String getWebDomain() {
1484             return mWebDomain;
1485         }
1486 
1487         /**
1488          * @hide
1489          */
setWebDomain(@ullable String domain)1490         public void setWebDomain(@Nullable String domain) {
1491             if (domain == null) return;
1492 
1493             Uri uri = Uri.parse(domain);
1494             if (uri == null) {
1495                 // Cannot log domain because it could contain PII;
1496                 Log.w(TAG, "Failed to parse web domain");
1497                 return;
1498             }
1499 
1500             mWebScheme = uri.getScheme();
1501             if (mWebScheme == null) {
1502                 uri = Uri.parse("http://" + domain);
1503             }
1504 
1505             mWebDomain = uri.getHost();
1506         }
1507 
1508         /**
1509          * Returns the scheme of the HTML document represented by this view.
1510          *
1511          * <p>Typically used when the view associated with the view is a container for an HTML
1512          * document.
1513          *
1514          * @return scheme-only part of the document. For example, if the full URL is
1515          * {@code https://example.com/login?user=my_user}, it returns {@code https}.
1516          */
getWebScheme()1517         @Nullable public String getWebScheme() {
1518             return mWebScheme;
1519         }
1520 
1521         /**
1522          * Returns the HTML properties associated with this view.
1523          *
1524          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1525          * not for assist purposes.
1526          *
1527          * @return the HTML properties associated with this view, or {@code null} if the
1528          * structure was created for assist purposes.
1529          */
getHtmlInfo()1530         @Nullable public HtmlInfo getHtmlInfo() {
1531             return mHtmlInfo;
1532         }
1533 
1534         /**
1535          * Returns the list of locales associated with this view.
1536          */
getLocaleList()1537         @Nullable public LocaleList getLocaleList() {
1538             return mLocaleList;
1539         }
1540 
1541         /**
1542          * Returns the MIME types accepted by {@link View#performReceiveContent} for this view. See
1543          * {@link View#getReceiveContentMimeTypes()} for details.
1544          */
1545         @Nullable
1546         @SuppressLint("NullableCollection")
getReceiveContentMimeTypes()1547         public String[] getReceiveContentMimeTypes() {
1548             return mReceiveContentMimeTypes;
1549         }
1550 
1551         /**
1552          * Returns any text associated with the node that is displayed to the user, or null
1553          * if there is none.
1554          */
1555         @Nullable
getText()1556         public CharSequence getText() {
1557             return mText != null ? mText.mText : null;
1558         }
1559 
1560         /**
1561          * If {@link #getText()} is non-null, this is where the current selection starts.
1562          *
1563          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1564          * not for autofill purposes.
1565          */
getTextSelectionStart()1566         public int getTextSelectionStart() {
1567             return mText != null ? mText.mTextSelectionStart : -1;
1568         }
1569 
1570         /**
1571          * If {@link #getText()} is non-null, this is where the current selection starts.
1572          * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
1573          * indicating the cursor position.
1574          *
1575          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1576          * not for autofill purposes.
1577          */
getTextSelectionEnd()1578         public int getTextSelectionEnd() {
1579             return mText != null ? mText.mTextSelectionEnd : -1;
1580         }
1581 
1582         /**
1583          * If {@link #getText()} is non-null, this is the main text color associated with it.
1584          * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
1585          * Note that the text may also contain style spans that modify the color of specific
1586          * parts of the text.
1587          */
getTextColor()1588         public int getTextColor() {
1589             return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
1590         }
1591 
1592         /**
1593          * If {@link #getText()} is non-null, this is the main text background color associated
1594          * with it.
1595          * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
1596          * Note that the text may also contain style spans that modify the color of specific
1597          * parts of the text.
1598          *
1599          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1600          * not for autofill purposes.
1601          */
getTextBackgroundColor()1602         public int getTextBackgroundColor() {
1603             return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
1604         }
1605 
1606         /**
1607          * If {@link #getText()} is non-null, this is the main text size (in pixels) associated
1608          * with it.
1609          * Note that the text may also contain style spans that modify the size of specific
1610          * parts of the text.
1611          *
1612          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1613          * not for autofill purposes.
1614          */
getTextSize()1615         public float getTextSize() {
1616             return mText != null ? mText.mTextSize : 0;
1617         }
1618 
1619         /**
1620          * If {@link #getText()} is non-null, this is the main text style associated
1621          * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
1622          * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
1623          * {@link #TEXT_STYLE_UNDERLINE}.
1624          * Note that the text may also contain style spans that modify the style of specific
1625          * parts of the text.
1626          *
1627          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1628          * not for autofill purposes.
1629          */
getTextStyle()1630         public int getTextStyle() {
1631             return mText != null ? mText.mTextStyle : 0;
1632         }
1633 
1634         /**
1635          * Return per-line offsets into the text returned by {@link #getText()}.  Each entry
1636          * in the array is a formatted line of text, and the value it contains is the offset
1637          * into the text string where that line starts.  May return null if there is no line
1638          * information.
1639          *
1640          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1641          * not for autofill purposes.
1642          */
1643         @Nullable
getTextLineCharOffsets()1644         public int[] getTextLineCharOffsets() {
1645             return mText != null ? mText.mLineCharOffsets : null;
1646         }
1647 
1648         /**
1649          * Return per-line baselines into the text returned by {@link #getText()}.  Each entry
1650          * in the array is a formatted line of text, and the value it contains is the baseline
1651          * where that text appears in the view.  May return null if there is no line
1652          * information.
1653          *
1654          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1655          * not for autofill purposes.
1656          */
1657         @Nullable
getTextLineBaselines()1658         public int[] getTextLineBaselines() {
1659             return mText != null ? mText.mLineBaselines : null;
1660         }
1661 
1662         /**
1663          * Gets the identifier used to set the text associated with this view.
1664          *
1665          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1666          * not for assist purposes.
1667          */
1668         @Nullable
getTextIdEntry()1669         public String getTextIdEntry() {
1670             return mTextIdEntry;
1671         }
1672 
1673         /**
1674          * Return additional hint text associated with the node; this is typically used with
1675          * a node that takes user input, describing to the user what the input means.
1676          */
1677         @Nullable
getHint()1678         public String getHint() {
1679             return mText != null ? mText.mHint : null;
1680         }
1681 
1682         /**
1683          * Gets the identifier used to set the hint associated with this view.
1684          *
1685          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1686          * not for assist purposes.
1687          */
1688         @Nullable
getHintIdEntry()1689         public String getHintIdEntry() {
1690             return mHintIdEntry;
1691         }
1692 
1693         /**
1694          * Return a Bundle containing optional vendor-specific extension information.
1695          */
1696         @Nullable
getExtras()1697         public Bundle getExtras() {
1698             return mExtras;
1699         }
1700 
1701         /**
1702          * Return the number of children this node has.
1703          */
getChildCount()1704         public int getChildCount() {
1705             return mChildren != null ? mChildren.length : 0;
1706         }
1707 
1708         /**
1709          * Return a child of this node, given an index value from 0 to
1710          * {@link #getChildCount()}-1.
1711          */
getChildAt(int index)1712         public ViewNode getChildAt(int index) {
1713             return mChildren[index];
1714         }
1715 
1716         /**
1717          * Returns the minimum width in ems of the text associated with this node, or {@code -1}
1718          * if not supported by the node.
1719          *
1720          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1721          * not for assist purposes.
1722          */
getMinTextEms()1723         public int getMinTextEms() {
1724             return mMinEms;
1725         }
1726 
1727         /**
1728          * Returns the maximum width in ems of the text associated with this node, or {@code -1}
1729          * if not supported by the node.
1730          *
1731          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1732          * not for assist purposes.
1733          */
getMaxTextEms()1734         public int getMaxTextEms() {
1735             return mMaxEms;
1736         }
1737 
1738         /**
1739          * Returns the maximum length of the text associated with this node, or {@code -1} if not
1740          * supported by the node or not set. System may set a default value if the text length is
1741          * not set.
1742          *
1743          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1744          * not for assist purposes.
1745          */
getMaxTextLength()1746         public int getMaxTextLength() {
1747             return mMaxLength;
1748         }
1749 
1750         /**
1751          * Gets the {@link View#setImportantForAutofill(int) importantForAutofill mode} of
1752          * the view associated with this node.
1753          *
1754          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
1755          */
getImportantForAutofill()1756         public @AutofillImportance int getImportantForAutofill() {
1757             return mImportantForAutofill;
1758         }
1759     }
1760 
1761     /**
1762      * A parcelable wrapper class around {@link ViewNode}.
1763      *
1764      * <p>This class, when parceled and unparceled, does not carry the child nodes.
1765      *
1766      * @hide
1767      */
1768     public static final class ViewNodeParcelable implements Parcelable {
1769 
1770         @NonNull
1771         private final ViewNode mViewNode;
1772 
ViewNodeParcelable(@onNull ViewNode viewNode)1773         public ViewNodeParcelable(@NonNull ViewNode viewNode) {
1774             mViewNode = viewNode;
1775         }
1776 
ViewNodeParcelable(@onNull Parcel in)1777         public ViewNodeParcelable(@NonNull Parcel in) {
1778             mViewNode = new ViewNode(in);
1779         }
1780 
1781         @NonNull
getViewNode()1782         public ViewNode getViewNode() {
1783             return mViewNode;
1784         }
1785 
1786         @Override
describeContents()1787         public int describeContents() {
1788             return 0;
1789         }
1790 
1791         @Override
writeToParcel(@onNull Parcel parcel, int flags)1792         public void writeToParcel(@NonNull Parcel parcel, int flags) {
1793             mViewNode.writeSelfToParcel(parcel, /*pwriter=*/null, /*sanitizeOnWrite=*/false,
1794                     /*tmpMatrix*/null, /*willWriteChildren=*/ false);
1795         }
1796 
1797         @NonNull
1798         public static final Parcelable.Creator<ViewNodeParcelable> CREATOR =
1799                 new Parcelable.Creator<ViewNodeParcelable>() {
1800                     @Override
1801                     public ViewNodeParcelable createFromParcel(@NonNull Parcel in) {
1802                         return new ViewNodeParcelable(in);
1803                     }
1804 
1805                     @Override
1806                     public ViewNodeParcelable[] newArray(int size) {
1807                         return new ViewNodeParcelable[size];
1808                     }
1809                 };
1810     }
1811 
1812     /**
1813      * POJO used to override some autofill-related values when the node is parcelized.
1814      *
1815      * @hide
1816      */
1817     static public class AutofillOverlay {
1818         public boolean focused;
1819         public AutofillValue value;
1820     }
1821 
1822     /**
1823      * @hide
1824      */
1825     public static class ViewNodeBuilder extends ViewStructure {
1826         final AssistStructure mAssist;
1827         final ViewNode mNode;
1828         final boolean mAsync;
1829 
1830         /**
1831          * Used to instantiate a builder for a stand-alone {@link ViewNode} which is not associated
1832          * to a properly created {@link AssistStructure}.
1833          */
ViewNodeBuilder()1834         public ViewNodeBuilder() {
1835             mAssist = new AssistStructure();
1836             mNode = new ViewNode();
1837             mAsync = false;
1838         }
1839 
ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async)1840         ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
1841             mAssist = assist;
1842             mNode = node;
1843             mAsync = async;
1844         }
1845 
1846         @NonNull
getViewNode()1847         public ViewNode getViewNode() {
1848             return mNode;
1849         }
1850 
1851         @Override
setId(int id, String packageName, String typeName, String entryName)1852         public void setId(int id, String packageName, String typeName, String entryName) {
1853             mNode.mId = id;
1854             mNode.mIdPackage = packageName;
1855             mNode.mIdType = typeName;
1856             mNode.mIdEntry = entryName;
1857         }
1858 
1859         @Override
setDimens(int left, int top, int scrollX, int scrollY, int width, int height)1860         public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
1861             mNode.mX = left;
1862             mNode.mY = top;
1863             mNode.mScrollX = scrollX;
1864             mNode.mScrollY = scrollY;
1865             mNode.mWidth = width;
1866             mNode.mHeight = height;
1867         }
1868 
1869         @Override
setTransformation(Matrix matrix)1870         public void setTransformation(Matrix matrix) {
1871             if (matrix == null) {
1872                 mNode.mMatrix = null;
1873             } else {
1874                 mNode.mMatrix = new Matrix(matrix);
1875             }
1876         }
1877 
1878         @Override
setElevation(float elevation)1879         public void setElevation(float elevation) {
1880             mNode.mElevation = elevation;
1881         }
1882 
1883         @Override
setAlpha(float alpha)1884         public void setAlpha(float alpha) {
1885             mNode.mAlpha = alpha;
1886         }
1887 
1888         @Override
setVisibility(int visibility)1889         public void setVisibility(int visibility) {
1890             mNode.mFlags = (mNode.mFlags & ~ViewNode.FLAGS_VISIBILITY_MASK)
1891                     | (visibility & ViewNode.FLAGS_VISIBILITY_MASK);
1892         }
1893 
1894         @Override
setAssistBlocked(boolean state)1895         public void setAssistBlocked(boolean state) {
1896             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED)
1897                     | (state ? ViewNode.FLAGS_ASSIST_BLOCKED : 0);
1898         }
1899 
1900         @Override
setEnabled(boolean state)1901         public void setEnabled(boolean state) {
1902             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED)
1903                     | (state ? 0 : ViewNode.FLAGS_DISABLED);
1904         }
1905 
1906         @Override
setClickable(boolean state)1907         public void setClickable(boolean state) {
1908             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE)
1909                     | (state ? ViewNode.FLAGS_CLICKABLE : 0);
1910         }
1911 
1912         @Override
setLongClickable(boolean state)1913         public void setLongClickable(boolean state) {
1914             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE)
1915                     | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0);
1916         }
1917 
1918         @Override
setContextClickable(boolean state)1919         public void setContextClickable(boolean state) {
1920             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE)
1921                     | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0);
1922         }
1923 
1924         @Override
setFocusable(boolean state)1925         public void setFocusable(boolean state) {
1926             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
1927                     | (state ? ViewNode.FLAGS_FOCUSABLE : 0);
1928         }
1929 
1930         @Override
setFocused(boolean state)1931         public void setFocused(boolean state) {
1932             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED)
1933                     | (state ? ViewNode.FLAGS_FOCUSED : 0);
1934         }
1935 
1936         @Override
setAccessibilityFocused(boolean state)1937         public void setAccessibilityFocused(boolean state) {
1938             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED)
1939                     | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0);
1940         }
1941 
1942         @Override
setCheckable(boolean state)1943         public void setCheckable(boolean state) {
1944             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE)
1945                     | (state ? ViewNode.FLAGS_CHECKABLE : 0);
1946         }
1947 
1948         @Override
setChecked(boolean state)1949         public void setChecked(boolean state) {
1950             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED)
1951                     | (state ? ViewNode.FLAGS_CHECKED : 0);
1952         }
1953 
1954         @Override
setSelected(boolean state)1955         public void setSelected(boolean state) {
1956             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED)
1957                     | (state ? ViewNode.FLAGS_SELECTED : 0);
1958         }
1959 
1960         @Override
setActivated(boolean state)1961         public void setActivated(boolean state) {
1962             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED)
1963                     | (state ? ViewNode.FLAGS_ACTIVATED : 0);
1964         }
1965 
1966         @Override
setOpaque(boolean opaque)1967         public void setOpaque(boolean opaque) {
1968             mNode.mFlags = (mNode.mFlags & ~ViewNode.FLAGS_OPAQUE)
1969                     | (opaque ? ViewNode.FLAGS_OPAQUE : 0);
1970         }
1971 
1972         @Override
setClassName(String className)1973         public void setClassName(String className) {
1974             mNode.mClassName = className;
1975         }
1976 
1977         @Override
setContentDescription(CharSequence contentDescription)1978         public void setContentDescription(CharSequence contentDescription) {
1979             mNode.mContentDescription = contentDescription;
1980         }
1981 
getNodeText()1982         private final ViewNodeText getNodeText() {
1983             if (mNode.mText != null) {
1984                 return mNode.mText;
1985             }
1986             mNode.mText = new ViewNodeText();
1987             return mNode.mText;
1988         }
1989 
1990         @Override
setText(CharSequence text)1991         public void setText(CharSequence text) {
1992             ViewNodeText t = getNodeText();
1993             t.mText = TextUtils.trimNoCopySpans(text);
1994             t.mTextSelectionStart = t.mTextSelectionEnd = -1;
1995         }
1996 
1997         @Override
setText(CharSequence text, int selectionStart, int selectionEnd)1998         public void setText(CharSequence text, int selectionStart, int selectionEnd) {
1999             ViewNodeText t = getNodeText();
2000             t.mText = TextUtils.trimNoCopySpans(text);
2001             t.mTextSelectionStart = selectionStart;
2002             t.mTextSelectionEnd = selectionEnd;
2003         }
2004 
2005         @Override
setTextStyle(float size, int fgColor, int bgColor, int style)2006         public void setTextStyle(float size, int fgColor, int bgColor, int style) {
2007             ViewNodeText t = getNodeText();
2008             t.mTextColor = fgColor;
2009             t.mTextBackgroundColor = bgColor;
2010             t.mTextSize = size;
2011             t.mTextStyle = style;
2012         }
2013 
2014         @Override
setTextLines(int[] charOffsets, int[] baselines)2015         public void setTextLines(int[] charOffsets, int[] baselines) {
2016             ViewNodeText t = getNodeText();
2017             t.mLineCharOffsets = charOffsets;
2018             t.mLineBaselines = baselines;
2019         }
2020 
2021         @Override
setTextIdEntry(@onNull String entryName)2022         public void setTextIdEntry(@NonNull String entryName) {
2023             mNode.mTextIdEntry = Objects.requireNonNull(entryName);
2024         }
2025 
2026         @Override
setHint(CharSequence hint)2027         public void setHint(CharSequence hint) {
2028             getNodeText().mHint = hint != null ? hint.toString() : null;
2029         }
2030 
2031         @Override
setHintIdEntry(@onNull String entryName)2032         public void setHintIdEntry(@NonNull String entryName) {
2033             mNode.mHintIdEntry = Objects.requireNonNull(entryName);
2034         }
2035 
2036         @Override
getText()2037         public CharSequence getText() {
2038             return mNode.mText != null ? mNode.mText.mText : null;
2039         }
2040 
2041         @Override
getTextSelectionStart()2042         public int getTextSelectionStart() {
2043             return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1;
2044         }
2045 
2046         @Override
getTextSelectionEnd()2047         public int getTextSelectionEnd() {
2048             return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1;
2049         }
2050 
2051         @Override
getHint()2052         public CharSequence getHint() {
2053             return mNode.mText != null ? mNode.mText.mHint : null;
2054         }
2055 
2056         @Override
getExtras()2057         public Bundle getExtras() {
2058             if (mNode.mExtras != null) {
2059                 return mNode.mExtras;
2060             }
2061             mNode.mExtras = new Bundle();
2062             return mNode.mExtras;
2063         }
2064 
2065         @Override
hasExtras()2066         public boolean hasExtras() {
2067             return mNode.mExtras != null;
2068         }
2069 
2070         @Override
setChildCount(int num)2071         public void setChildCount(int num) {
2072             mNode.mChildren = new ViewNode[num];
2073         }
2074 
2075         @Override
addChildCount(int num)2076         public int addChildCount(int num) {
2077             if (mNode.mChildren == null) {
2078                 setChildCount(num);
2079                 return 0;
2080             }
2081             final int start = mNode.mChildren.length;
2082             ViewNode[] newArray = new ViewNode[start + num];
2083             System.arraycopy(mNode.mChildren, 0, newArray, 0, start);
2084             mNode.mChildren = newArray;
2085             return start;
2086         }
2087 
2088         @Override
getChildCount()2089         public int getChildCount() {
2090             return mNode.mChildren != null ? mNode.mChildren.length : 0;
2091         }
2092 
2093         @Override
newChild(int index)2094         public ViewStructure newChild(int index) {
2095             ViewNode node = new ViewNode();
2096             mNode.mChildren[index] = node;
2097             return new ViewNodeBuilder(mAssist, node, false);
2098         }
2099 
2100         @Override
asyncNewChild(int index)2101         public ViewStructure asyncNewChild(int index) {
2102             synchronized (mAssist) {
2103                 ViewNode node = new ViewNode();
2104                 mNode.mChildren[index] = node;
2105                 ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
2106                 mAssist.mPendingAsyncChildren.add(builder);
2107                 return builder;
2108             }
2109         }
2110 
2111         @Override
asyncCommit()2112         public void asyncCommit() {
2113             synchronized (mAssist) {
2114                 if (!mAsync) {
2115                     throw new IllegalStateException("Child " + this
2116                             + " was not created with ViewStructure.asyncNewChild");
2117                 }
2118                 if (!mAssist.mPendingAsyncChildren.remove(this)) {
2119                     throw new IllegalStateException("Child " + this + " already committed");
2120                 }
2121                 mAssist.notifyAll();
2122             }
2123         }
2124 
2125         @Override
getTempRect()2126         public Rect getTempRect() {
2127             return mAssist.mTmpRect;
2128         }
2129 
2130         @Override
setAutofillId(@onNull AutofillId id)2131         public void setAutofillId(@NonNull AutofillId id) {
2132             mNode.mAutofillId = id;
2133         }
2134 
2135         @Override
setAutofillId(@onNull AutofillId parentId, int virtualId)2136         public void setAutofillId(@NonNull AutofillId parentId, int virtualId) {
2137             mNode.mAutofillId = new AutofillId(parentId, virtualId);
2138         }
2139 
2140         @Override
getAutofillId()2141         public AutofillId getAutofillId() {
2142             return mNode.mAutofillId;
2143         }
2144 
2145         @Override
setAutofillType(@iew.AutofillType int type)2146         public void setAutofillType(@View.AutofillType int type) {
2147             mNode.mAutofillType = type;
2148         }
2149 
2150         @Override
setAutofillHints(@ullable String[] hints)2151         public void setAutofillHints(@Nullable String[] hints) {
2152             mNode.mAutofillHints = hints;
2153         }
2154 
2155         @Override
setAutofillValue(AutofillValue value)2156         public void setAutofillValue(AutofillValue value) {
2157             mNode.mAutofillValue = value;
2158         }
2159 
2160         @Override
setAutofillOptions(CharSequence[] options)2161         public void setAutofillOptions(CharSequence[] options) {
2162             mNode.mAutofillOptions = options;
2163         }
2164 
2165         @Override
setImportantForAutofill(@utofillImportance int mode)2166         public void setImportantForAutofill(@AutofillImportance int mode) {
2167             mNode.mImportantForAutofill = mode;
2168         }
2169 
2170         @Override
setReceiveContentMimeTypes(@ullable String[] mimeTypes)2171         public void setReceiveContentMimeTypes(@Nullable String[] mimeTypes) {
2172             mNode.mReceiveContentMimeTypes = mimeTypes;
2173         }
2174 
2175         @Override
setInputType(int inputType)2176         public void setInputType(int inputType) {
2177             mNode.mInputType = inputType;
2178         }
2179 
2180         @Override
setMinTextEms(int minEms)2181         public void setMinTextEms(int minEms) {
2182             mNode.mMinEms = minEms;
2183         }
2184 
2185         @Override
setMaxTextEms(int maxEms)2186         public void setMaxTextEms(int maxEms) {
2187             mNode.mMaxEms = maxEms;
2188         }
2189 
2190         @Override
setMaxTextLength(int maxLength)2191         public void setMaxTextLength(int maxLength) {
2192             mNode.mMaxLength = maxLength;
2193         }
2194 
2195         @Override
setDataIsSensitive(boolean sensitive)2196         public void setDataIsSensitive(boolean sensitive) {
2197             mNode.mSanitized = !sensitive;
2198         }
2199 
2200         @Override
setWebDomain(@ullable String domain)2201         public void setWebDomain(@Nullable String domain) {
2202             mNode.setWebDomain(domain);
2203         }
2204 
2205         @Override
setLocaleList(LocaleList localeList)2206         public void setLocaleList(LocaleList localeList) {
2207             mNode.mLocaleList = localeList;
2208         }
2209 
2210         @Override
newHtmlInfoBuilder(@onNull String tagName)2211         public HtmlInfo.Builder newHtmlInfoBuilder(@NonNull String tagName) {
2212             return new HtmlInfoNodeBuilder(tagName);
2213         }
2214 
2215         @Override
setHtmlInfo(@onNull HtmlInfo htmlInfo)2216         public void setHtmlInfo(@NonNull HtmlInfo htmlInfo) {
2217             mNode.mHtmlInfo = htmlInfo;
2218         }
2219     }
2220 
2221     private static final class HtmlInfoNode extends HtmlInfo implements Parcelable {
2222         private final String mTag;
2223         private final String[] mNames;
2224         private final String[] mValues;
2225 
2226         // Not parcelable
2227         private ArrayList<Pair<String, String>> mAttributes;
2228 
HtmlInfoNode(HtmlInfoNodeBuilder builder)2229         private HtmlInfoNode(HtmlInfoNodeBuilder builder) {
2230             mTag = builder.mTag;
2231             if (builder.mNames == null) {
2232                 mNames = null;
2233                 mValues = null;
2234             } else {
2235                 mNames = new String[builder.mNames.size()];
2236                 mValues = new String[builder.mValues.size()];
2237                 builder.mNames.toArray(mNames);
2238                 builder.mValues.toArray(mValues);
2239             }
2240         }
2241 
2242         @Override
getTag()2243         public String getTag() {
2244             return mTag;
2245         }
2246 
2247         @Override
getAttributes()2248         public List<Pair<String, String>> getAttributes() {
2249             if (mAttributes == null && mNames != null) {
2250                 mAttributes = new ArrayList<>(mNames.length);
2251                 for (int i = 0; i < mNames.length; i++) {
2252                     final Pair<String, String> pair = new Pair<>(mNames[i], mValues[i]);
2253                     mAttributes.add(i, pair);
2254                 }
2255             }
2256             return mAttributes;
2257         }
2258 
2259         @Override
describeContents()2260         public int describeContents() {
2261             return 0;
2262         }
2263 
2264         @Override
writeToParcel(Parcel parcel, int flags)2265         public void writeToParcel(Parcel parcel, int flags) {
2266             parcel.writeString(mTag);
2267             parcel.writeStringArray(mNames);
2268             parcel.writeStringArray(mValues);
2269         }
2270 
2271         @SuppressWarnings("hiding")
2272         public static final @android.annotation.NonNull Creator<HtmlInfoNode> CREATOR = new Creator<HtmlInfoNode>() {
2273             @Override
2274             public HtmlInfoNode createFromParcel(Parcel parcel) {
2275                 // Always go through the builder to ensure the data ingested by
2276                 // the system obeys the contract of the builder to avoid attacks
2277                 // using specially crafted parcels.
2278                 final String tag = parcel.readString();
2279                 final HtmlInfoNodeBuilder builder = new HtmlInfoNodeBuilder(tag);
2280                 final String[] names = parcel.readStringArray();
2281                 final String[] values = parcel.readStringArray();
2282                 if (names != null && values != null) {
2283                     if (names.length != values.length) {
2284                         Log.w(TAG, "HtmlInfo attributes mismatch: names=" + names.length
2285                                 + ", values=" + values.length);
2286                     } else {
2287                         for (int i = 0; i < names.length; i++) {
2288                             builder.addAttribute(names[i], values[i]);
2289                         }
2290                     }
2291                 }
2292                 return builder.build();
2293             }
2294 
2295             @Override
2296             public HtmlInfoNode[] newArray(int size) {
2297                 return new HtmlInfoNode[size];
2298             }
2299         };
2300     }
2301 
2302     private static final class HtmlInfoNodeBuilder extends HtmlInfo.Builder {
2303         private final String mTag;
2304         private ArrayList<String> mNames;
2305         private ArrayList<String> mValues;
2306 
HtmlInfoNodeBuilder(String tag)2307         HtmlInfoNodeBuilder(String tag) {
2308             mTag = tag;
2309         }
2310 
2311         @Override
addAttribute(String name, String value)2312         public Builder addAttribute(String name, String value) {
2313             if (mNames == null) {
2314                 mNames = new ArrayList<>();
2315                 mValues = new ArrayList<>();
2316             }
2317             mNames.add(name);
2318             mValues.add(value);
2319             return this;
2320         }
2321 
2322         @Override
build()2323         public HtmlInfoNode build() {
2324             return new HtmlInfoNode(this);
2325         }
2326     }
2327 
2328     /** @hide */
AssistStructure(Activity activity, boolean forAutoFill, int flags)2329     public AssistStructure(Activity activity, boolean forAutoFill, int flags) {
2330         mHaveData = true;
2331         mFlags = flags;
2332         ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
2333                 activity.getActivityToken());
2334         for (int i=0; i<views.size(); i++) {
2335             ViewRootImpl root = views.get(i);
2336             if (root.getView() == null) {
2337                 Log.w(TAG, "Skipping window with dettached view: " + root.getTitle());
2338                 continue;
2339             }
2340             mWindowNodes.add(new WindowNode(this, root, forAutoFill, flags));
2341         }
2342     }
2343 
AssistStructure()2344     public AssistStructure() {
2345         mHaveData = true;
2346         mFlags = 0;
2347     }
2348 
2349     /** @hide */
AssistStructure(Parcel in)2350     public AssistStructure(Parcel in) {
2351         mTaskId = in.readInt();
2352         mActivityComponent = ComponentName.readFromParcel(in);
2353         mIsHomeActivity = in.readInt() == 1;
2354         mReceiveChannel = in.readStrongBinder();
2355     }
2356 
2357     /**
2358      * Helper method used to sanitize the structure before it's written to a parcel.
2359      *
2360      * <p>Used just on autofill.
2361      * @hide
2362      */
sanitizeForParceling(boolean sanitize)2363     public void sanitizeForParceling(boolean sanitize) {
2364         mSanitizeOnWrite = sanitize;
2365     }
2366 
2367     /** @hide */
dump(boolean showSensitive)2368     public void dump(boolean showSensitive) {
2369         if (mActivityComponent == null) {
2370             Log.i(TAG, "dump(): calling ensureData() first");
2371             ensureData();
2372         }
2373         Log.i(TAG, "Task id: " + mTaskId);
2374         Log.i(TAG, "Activity: " + (mActivityComponent != null
2375                 ? mActivityComponent.flattenToShortString()
2376                 : null));
2377         Log.i(TAG, "Sanitize on write: " + mSanitizeOnWrite);
2378         Log.i(TAG, "Flags: " + mFlags);
2379         final int N = getWindowNodeCount();
2380         for (int i=0; i<N; i++) {
2381             WindowNode node = getWindowNodeAt(i);
2382             Log.i(TAG, "Window #" + i + " [" + node.getLeft() + "," + node.getTop()
2383                     + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getTitle());
2384             dump("  ", node.getRootViewNode(), showSensitive);
2385         }
2386     }
2387 
dump(String prefix, ViewNode node, boolean showSensitive)2388     void dump(String prefix, ViewNode node, boolean showSensitive) {
2389         Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop()
2390                 + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName());
2391         int id = node.getId();
2392         if (id != 0) {
2393             StringBuilder sb = new StringBuilder();
2394             sb.append(prefix); sb.append("  ID: #"); sb.append(Integer.toHexString(id));
2395             String entry = node.getIdEntry();
2396             if (entry != null) {
2397                 String type = node.getIdType();
2398                 String pkg = node.getIdPackage();
2399                 sb.append(" "); sb.append(pkg); sb.append(":"); sb.append(type);
2400                 sb.append("/"); sb.append(entry);
2401             }
2402             Log.i(TAG, sb.toString());
2403         }
2404         int scrollX = node.getScrollX();
2405         int scrollY = node.getScrollY();
2406         if (scrollX != 0 || scrollY != 0) {
2407             Log.i(TAG, prefix + "  Scroll: " + scrollX + "," + scrollY);
2408         }
2409         Matrix matrix = node.getTransformation();
2410         if (matrix != null) {
2411             Log.i(TAG, prefix + "  Transformation: " + matrix);
2412         }
2413         float elevation = node.getElevation();
2414         if (elevation != 0) {
2415             Log.i(TAG, prefix + "  Elevation: " + elevation);
2416         }
2417         float alpha = node.getAlpha();
2418         if (alpha != 0) {
2419             Log.i(TAG, prefix + "  Alpha: " + elevation);
2420         }
2421         CharSequence contentDescription = node.getContentDescription();
2422         if (contentDescription != null) {
2423             Log.i(TAG, prefix + "  Content description: " + contentDescription);
2424         }
2425         CharSequence text = node.getText();
2426         if (text != null) {
2427             final String safeText = node.isSanitized() || showSensitive ? text.toString()
2428                     : "REDACTED[" + text.length() + " chars]";
2429             Log.i(TAG, prefix + "  Text (sel " + node.getTextSelectionStart() + "-"
2430                     + node.getTextSelectionEnd() + "): " + safeText);
2431             Log.i(TAG, prefix + "  Text size: " + node.getTextSize() + " , style: #"
2432                     + node.getTextStyle());
2433             Log.i(TAG, prefix + "  Text color fg: #" + Integer.toHexString(node.getTextColor())
2434                     + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
2435             Log.i(TAG, prefix + "  Input type: " + node.getInputType());
2436             Log.i(TAG, prefix + "  Resource id: " + node.getTextIdEntry());
2437         }
2438         String webDomain = node.getWebDomain();
2439         if (webDomain != null) {
2440             Log.i(TAG, prefix + "  Web domain: " + webDomain);
2441         }
2442         HtmlInfo htmlInfo = node.getHtmlInfo();
2443         if (htmlInfo != null) {
2444             Log.i(TAG, prefix + "  HtmlInfo: tag=" + htmlInfo.getTag()
2445                     + ", attr="+ htmlInfo.getAttributes());
2446         }
2447 
2448         LocaleList localeList = node.getLocaleList();
2449         if (localeList != null) {
2450             Log.i(TAG, prefix + "  LocaleList: " + localeList);
2451         }
2452         String[] mimeTypes = node.getReceiveContentMimeTypes();
2453         if (mimeTypes != null) {
2454             Log.i(TAG, prefix + "  MIME types: " + Arrays.toString(mimeTypes));
2455         }
2456         String hint = node.getHint();
2457         if (hint != null) {
2458             Log.i(TAG, prefix + "  Hint: " + hint);
2459             Log.i(TAG, prefix + "  Resource id: " + node.getHintIdEntry());
2460         }
2461         Bundle extras = node.getExtras();
2462         if (extras != null) {
2463             Log.i(TAG, prefix + "  Extras: " + extras);
2464         }
2465         if (node.isAssistBlocked()) {
2466             Log.i(TAG, prefix + "  BLOCKED");
2467         }
2468         AutofillId autofillId = node.getAutofillId();
2469         if (autofillId == null) {
2470             Log.i(TAG, prefix + " NO autofill ID");
2471         } else {
2472             Log.i(TAG, prefix + "  Autofill info: id= " + autofillId
2473                     + ", type=" + node.getAutofillType()
2474                     + ", options=" + Arrays.toString(node.getAutofillOptions())
2475                     + ", hints=" + Arrays.toString(node.getAutofillHints())
2476                     + ", value=" + node.getAutofillValue()
2477                     + ", sanitized=" + node.isSanitized()
2478                     + ", important=" + node.getImportantForAutofill());
2479         }
2480 
2481         final int NCHILDREN = node.getChildCount();
2482         if (NCHILDREN > 0) {
2483             Log.i(TAG, prefix + "  Children:");
2484             String cprefix = prefix + "    ";
2485             for (int i=0; i<NCHILDREN; i++) {
2486                 ViewNode cnode = node.getChildAt(i);
2487                 dump(cprefix, cnode, showSensitive);
2488             }
2489         }
2490     }
2491 
2492     /**
2493      * Sets the task id is associated with the activity from which this AssistStructure was
2494      * generated.
2495      * @hide
2496      */
setTaskId(int taskId)2497     public void setTaskId(int taskId) {
2498         mTaskId = taskId;
2499     }
2500 
2501     /**
2502      * @return The task id for the associated activity.
2503      *
2504      * @hide
2505      */
getTaskId()2506     public int getTaskId() {
2507         return mTaskId;
2508     }
2509 
2510     /**
2511      * Sets the activity that is associated with this AssistStructure.
2512      * @hide
2513      */
setActivityComponent(ComponentName componentName)2514     public void setActivityComponent(ComponentName componentName) {
2515         mActivityComponent = componentName;
2516     }
2517 
2518     /**
2519      * Return the activity this AssistStructure came from.
2520      */
getActivityComponent()2521     public ComponentName getActivityComponent() {
2522         return mActivityComponent;
2523     }
2524 
2525     /** @hide */
getFlags()2526     public int getFlags() {
2527         return mFlags;
2528     }
2529 
2530     /**
2531      * Returns whether the activity associated with this AssistStructure was the home activity
2532      * (Launcher) at the time the assist data was acquired.
2533      * @return Whether the activity was the home activity.
2534      * @see android.content.Intent#CATEGORY_HOME
2535      */
isHomeActivity()2536     public boolean isHomeActivity() {
2537         return mIsHomeActivity;
2538     }
2539 
2540     /**
2541      * Return the number of window contents that have been collected in this assist data.
2542      */
getWindowNodeCount()2543     public int getWindowNodeCount() {
2544         ensureData();
2545         return mWindowNodes.size();
2546     }
2547 
2548     /**
2549      * Return one of the windows in the assist data.
2550      * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1.
2551      */
getWindowNodeAt(int index)2552     public WindowNode getWindowNodeAt(int index) {
2553         ensureData();
2554         return mWindowNodes.get(index);
2555     }
2556 
2557     // TODO(b/35708678): temporary method that disable one-way warning flag on binder.
2558     /** @hide */
ensureDataForAutofill()2559     public void ensureDataForAutofill() {
2560         if (mHaveData) {
2561             return;
2562         }
2563         mHaveData = true;
2564         Binder.allowBlocking(mReceiveChannel);
2565         try {
2566             ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
2567             reader.go();
2568         } finally {
2569             Binder.defaultBlocking(mReceiveChannel);
2570         }
2571     }
2572 
2573     /** @hide */
ensureData()2574     public void ensureData() {
2575         if (mHaveData) {
2576             return;
2577         }
2578         mHaveData = true;
2579         ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
2580         reader.go();
2581     }
2582 
waitForReady()2583     boolean waitForReady() {
2584         boolean skipStructure = false;
2585         synchronized (this) {
2586             long endTime = SystemClock.uptimeMillis() + 5000;
2587             long now;
2588             while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) {
2589                 try {
2590                     wait(endTime-now);
2591                 } catch (InterruptedException e) {
2592                 }
2593             }
2594             if (mPendingAsyncChildren.size() > 0) {
2595                 // We waited too long, assume none of the assist structure is valid.
2596                 Log.w(TAG, "Skipping assist structure, waiting too long for async children (have "
2597                         + mPendingAsyncChildren.size() + " remaining");
2598                 skipStructure = true;
2599             }
2600         }
2601         return !skipStructure;
2602     }
2603 
2604     /** @hide */
clearSendChannel()2605     public void clearSendChannel() {
2606         if (mSendChannel != null) {
2607             mSendChannel.mAssistStructure = null;
2608         }
2609     }
2610 
2611     @Override
describeContents()2612     public int describeContents() {
2613         return 0;
2614     }
2615 
2616     @Override
writeToParcel(Parcel out, int flags)2617     public void writeToParcel(Parcel out, int flags) {
2618         out.writeInt(mTaskId);
2619         ComponentName.writeToParcel(mActivityComponent, out);
2620         out.writeInt(mIsHomeActivity ? 1 : 0);
2621         if (mHaveData) {
2622             // This object holds its data.  We want to write a send channel that the
2623             // other side can use to retrieve that data.
2624             if (mSendChannel == null) {
2625                 mSendChannel = new SendChannel(this);
2626             }
2627             out.writeStrongBinder(mSendChannel);
2628         } else {
2629             // This object doesn't hold its data, so just propagate along its receive channel.
2630             out.writeStrongBinder(mReceiveChannel);
2631         }
2632     }
2633 
2634     public static final @android.annotation.NonNull Parcelable.Creator<AssistStructure> CREATOR
2635             = new Parcelable.Creator<AssistStructure>() {
2636         @Override
2637         public AssistStructure createFromParcel(Parcel in) {
2638             return new AssistStructure(in);
2639         }
2640 
2641         @Override
2642         public AssistStructure[] newArray(int size) {
2643             return new AssistStructure[size];
2644         }
2645     };
2646 }
2647