• 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         // TODO: The FLAGS_* below have filled all bits, will need to be refactored.
662         static final int FLAGS_DISABLED = 0x00000001;
663         static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
664         static final int FLAGS_FOCUSABLE = 0x00000010;
665         static final int FLAGS_FOCUSED = 0x00000020;
666         static final int FLAGS_SELECTED = 0x00000040;
667         static final int FLAGS_ASSIST_BLOCKED = 0x00000080;
668         static final int FLAGS_CHECKABLE = 0x00000100;
669         static final int FLAGS_CHECKED = 0x00000200;
670         static final int FLAGS_CLICKABLE = 0x00000400;
671         static final int FLAGS_LONG_CLICKABLE = 0x00000800;
672         static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x00001000;
673         static final int FLAGS_ACTIVATED = 0x00002000;
674         static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000;
675         static final int FLAGS_OPAQUE = 0x00008000;
676 
677         // --IMPORTANT-- must update this flag if any below flags extend to further bits.
678         // This flag is used to clear all FLAGS_HAS_* values in mFlags prior to parceling.
679         static final int FLAGS_ALL_CONTROL = 0xffff0000;
680 
681         static final int FLAGS_HAS_MIME_TYPES = 0x80000000;
682         static final int FLAGS_HAS_MATRIX = 0x40000000;
683         static final int FLAGS_HAS_ALPHA = 0x20000000;
684         static final int FLAGS_HAS_ELEVATION = 0x10000000;
685         static final int FLAGS_HAS_SCROLL = 0x08000000;
686         static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
687         static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
688         static final int FLAGS_HAS_TEXT = 0x01000000;
689         static final int FLAGS_HAS_COMPLEX_TEXT = 0x00800000;
690         static final int FLAGS_HAS_EXTRAS = 0x00400000;
691         static final int FLAGS_HAS_ID = 0x00200000;
692         static final int FLAGS_HAS_CHILDREN = 0x00100000;
693         static final int FLAGS_HAS_URL_DOMAIN = 0x00080000;
694         static final int FLAGS_HAS_INPUT_TYPE = 0x00040000;
695         static final int FLAGS_HAS_URL_SCHEME = 0x00020000;
696         static final int FLAGS_HAS_LOCALE_LIST = 0x00010000;
697         // --IMPORTANT END--
698 
699         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID =         0x0001;
700         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID = 0x0002;
701         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE =           0x0004;
702         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE =            0x0008;
703         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS =           0x0010;
704         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS =         0x0020;
705         static final int AUTOFILL_FLAGS_HAS_HTML_INFO =                0x0040;
706         static final int AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY =            0x0080;
707         static final int AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS =             0x0100;
708         static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS =             0x0200;
709         static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH =          0x0400;
710         static final int AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID =      0x0800;
711         static final int AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY =            0x1000;
712 
713         int mFlags;
714         int mAutofillFlags;
715 
716         String mClassName;
717         CharSequence mContentDescription;
718 
719         ViewNodeText mText;
720         int mInputType;
721         String mWebScheme;
722         String mWebDomain;
723         Bundle mExtras;
724         LocaleList mLocaleList;
725         String[] mReceiveContentMimeTypes;
726 
727         ViewNode[] mChildren;
728 
729         // TODO(b/111276913): temporarily made public / @hide until we decide what will be used by
730         // COntent Capture.
731         /** @hide */
732         @SystemApi
ViewNode()733         public ViewNode() {
734         }
735 
ViewNode(@onNull Parcel in)736         ViewNode(@NonNull Parcel in) {
737             initializeFromParcelWithoutChildren(in, /*preader=*/null, /*tmpMatrix=*/null);
738         }
739 
ViewNode(ParcelTransferReader reader, int nestingLevel)740         ViewNode(ParcelTransferReader reader, int nestingLevel) {
741             final Parcel in = reader.readParcel(VALIDATE_VIEW_TOKEN, nestingLevel);
742             reader.mNumReadViews++;
743             initializeFromParcelWithoutChildren(in, Objects.requireNonNull(reader.mStringReader),
744                     Objects.requireNonNull(reader.mTmpMatrix));
745             if ((mFlags & FLAGS_HAS_CHILDREN) != 0) {
746                 final int numChildren = in.readInt();
747                 if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) {
748                     Log.d(TAG,
749                             "Preparing to read " + numChildren
750                                     + " children: @ #" + reader.mNumReadViews
751                                     + ", level " + nestingLevel);
752                 }
753                 mChildren = new ViewNode[numChildren];
754                 for (int i = 0; i < numChildren; i++) {
755                     mChildren[i] = new ViewNode(reader, nestingLevel + 1);
756                 }
757             }
758         }
759 
writeString(@onNull Parcel out, @Nullable PooledStringWriter pwriter, @Nullable String str)760         private static void writeString(@NonNull Parcel out, @Nullable PooledStringWriter pwriter,
761                 @Nullable String str) {
762             if (pwriter != null) {
763                 pwriter.writeString(str);
764             } else {
765                 out.writeString(str);
766             }
767         }
768 
769         @Nullable
readString(@onNull Parcel in, @Nullable PooledStringReader preader)770         private static String readString(@NonNull Parcel in, @Nullable PooledStringReader preader) {
771             if (preader != null) {
772                 return preader.readString();
773             }
774             return in.readString();
775         }
776 
777         // This does not read the child nodes.
initializeFromParcelWithoutChildren(Parcel in, @Nullable PooledStringReader preader, @Nullable float[] tmpMatrix)778         void initializeFromParcelWithoutChildren(Parcel in, @Nullable PooledStringReader preader,
779                 @Nullable float[] tmpMatrix) {
780             mClassName = readString(in, preader);
781             mFlags = in.readInt();
782             final int flags = mFlags;
783             mAutofillFlags = in.readInt();
784             final int autofillFlags = mAutofillFlags;
785             if ((flags&FLAGS_HAS_ID) != 0) {
786                 mId = in.readInt();
787                 if (mId != View.NO_ID) {
788                     mIdEntry = readString(in, preader);
789                     if (mIdEntry != null) {
790                         mIdType = readString(in, preader);
791                         mIdPackage = readString(in, preader);
792                     }
793                 }
794             }
795 
796             if (autofillFlags != 0) {
797                 mSanitized = in.readInt() == 1;
798                 mImportantForAutofill = in.readInt();
799 
800                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID) != 0) {
801                     int autofillViewId = in.readInt();
802                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID) != 0) {
803                         mAutofillId = new AutofillId(autofillViewId, in.readInt());
804                     } else {
805                         mAutofillId = new AutofillId(autofillViewId);
806                     }
807                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID) != 0) {
808                         mAutofillId.setSessionId(in.readInt());
809                     }
810                 }
811                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
812                     mAutofillType = in.readInt();
813                 }
814                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS) != 0) {
815                     mAutofillHints = in.readStringArray();
816                 }
817                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE) != 0) {
818                     mAutofillValue = in.readParcelable(null, android.view.autofill.AutofillValue.class);
819                 }
820                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
821                     mAutofillOptions = in.readCharSequenceArray();
822                 }
823                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HTML_INFO) != 0) {
824                     mHtmlInfo = in.readParcelable(null, android.view.ViewStructure.HtmlInfo.class);
825                 }
826                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS) != 0) {
827                     mMinEms = in.readInt();
828                 }
829                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS) != 0) {
830                     mMaxEms = in.readInt();
831                 }
832                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
833                     mMaxLength = in.readInt();
834                 }
835                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
836                     mTextIdEntry = readString(in, preader);
837                 }
838                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY) != 0) {
839                     mHintIdEntry = readString(in, preader);
840                 }
841             }
842             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
843                 mX = in.readInt();
844                 mY = in.readInt();
845                 mWidth = in.readInt();
846                 mHeight = in.readInt();
847             } else {
848                 int val = in.readInt();
849                 mX = val&0x7fff;
850                 mY = (val>>16)&0x7fff;
851                 val = in.readInt();
852                 mWidth = val&0x7fff;
853                 mHeight = (val>>16)&0x7fff;
854             }
855             if ((flags&FLAGS_HAS_SCROLL) != 0) {
856                 mScrollX = in.readInt();
857                 mScrollY = in.readInt();
858             }
859             if ((flags&FLAGS_HAS_MATRIX) != 0) {
860                 mMatrix = new Matrix();
861                 if (tmpMatrix == null) {
862                     tmpMatrix = new float[9];
863                 }
864                 in.readFloatArray(tmpMatrix);
865                 mMatrix.setValues(tmpMatrix);
866             }
867             if ((flags&FLAGS_HAS_ELEVATION) != 0) {
868                 mElevation = in.readFloat();
869             }
870             if ((flags&FLAGS_HAS_ALPHA) != 0) {
871                 mAlpha = in.readFloat();
872             }
873             if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
874                 mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
875             }
876             if ((flags&FLAGS_HAS_TEXT) != 0) {
877                 mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
878             }
879             if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
880                 mInputType = in.readInt();
881             }
882             if ((flags&FLAGS_HAS_URL_SCHEME) != 0) {
883                 mWebScheme = in.readString();
884             }
885             if ((flags&FLAGS_HAS_URL_DOMAIN) != 0) {
886                 mWebDomain = in.readString();
887             }
888             if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) {
889                 mLocaleList = in.readParcelable(null, android.os.LocaleList.class);
890             }
891             if ((flags & FLAGS_HAS_MIME_TYPES) != 0) {
892                 mReceiveContentMimeTypes = in.readStringArray();
893             }
894             if ((flags&FLAGS_HAS_EXTRAS) != 0) {
895                 mExtras = in.readBundle();
896             }
897         }
898 
899         /**
900          * This does not write the child nodes.
901          *
902          * @param willWriteChildren whether child nodes will be written to the parcel or not after
903          *                          calling this method.
904          */
writeSelfToParcel(@onNull Parcel out, @Nullable PooledStringWriter pwriter, boolean sanitizeOnWrite, @Nullable float[] tmpMatrix, boolean willWriteChildren)905         int writeSelfToParcel(@NonNull Parcel out, @Nullable PooledStringWriter pwriter,
906                 boolean sanitizeOnWrite, @Nullable float[] tmpMatrix, boolean willWriteChildren) {
907             // Guard used to skip non-sanitized data when writing for autofill.
908             boolean writeSensitive = true;
909 
910             int flags = mFlags & ~FLAGS_ALL_CONTROL;
911             int autofillFlags = 0;
912 
913             if (mId != View.NO_ID) {
914                 flags |= FLAGS_HAS_ID;
915             }
916             if ((mX&~0x7fff) != 0 || (mY&~0x7fff) != 0
917                     || (mWidth&~0x7fff) != 0 | (mHeight&~0x7fff) != 0) {
918                 flags |= FLAGS_HAS_LARGE_COORDS;
919             }
920             if (mScrollX != 0 || mScrollY != 0) {
921                 flags |= FLAGS_HAS_SCROLL;
922             }
923             if (mMatrix != null) {
924                 flags |= FLAGS_HAS_MATRIX;
925             }
926             if (mElevation != 0) {
927                 flags |= FLAGS_HAS_ELEVATION;
928             }
929             if (mAlpha != 1.0f) {
930                 flags |= FLAGS_HAS_ALPHA;
931             }
932             if (mContentDescription != null) {
933                 flags |= FLAGS_HAS_CONTENT_DESCRIPTION;
934             }
935             if (mText != null) {
936                 flags |= FLAGS_HAS_TEXT;
937                 if (!mText.isSimple()) {
938                     flags |= FLAGS_HAS_COMPLEX_TEXT;
939                 }
940             }
941             if (mInputType != 0) {
942                 flags |= FLAGS_HAS_INPUT_TYPE;
943             }
944             if (mWebScheme != null) {
945                 flags |= FLAGS_HAS_URL_SCHEME;
946             }
947             if (mWebDomain != null) {
948                 flags |= FLAGS_HAS_URL_DOMAIN;
949             }
950             if (mLocaleList != null) {
951                 flags |= FLAGS_HAS_LOCALE_LIST;
952             }
953             if (mReceiveContentMimeTypes != null) {
954                 flags |= FLAGS_HAS_MIME_TYPES;
955             }
956             if (mExtras != null) {
957                 flags |= FLAGS_HAS_EXTRAS;
958             }
959             if (mChildren != null && willWriteChildren) {
960                 flags |= FLAGS_HAS_CHILDREN;
961             }
962             if (mAutofillId != null) {
963                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID;
964                 if (mAutofillId.isVirtualInt()) {
965                     autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID;
966                 }
967                 if (mAutofillId.hasSession()) {
968                     autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID;
969                 }
970             }
971             if (mAutofillValue != null) {
972                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE;
973             }
974             if (mAutofillType != View.AUTOFILL_TYPE_NONE) {
975                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE;
976             }
977             if (mAutofillHints != null) {
978                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS;
979             }
980             if (mAutofillOptions != null) {
981                 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS;
982             }
983             if (mHtmlInfo instanceof Parcelable) {
984                 autofillFlags |= AUTOFILL_FLAGS_HAS_HTML_INFO;
985             }
986             if (mMinEms > -1) {
987                 autofillFlags |= AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS;
988             }
989             if (mMaxEms > -1) {
990                 autofillFlags |= AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS;
991             }
992             if (mMaxLength > -1) {
993                 autofillFlags |= AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH;
994             }
995             if (mTextIdEntry != null) {
996                 autofillFlags |= AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY;
997             }
998             if (mHintIdEntry != null) {
999                 autofillFlags |= AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY;
1000             }
1001 
1002             writeString(out, pwriter, mClassName);
1003 
1004             int writtenFlags = flags;
1005             if (autofillFlags != 0 && (mSanitized || !sanitizeOnWrite)) {
1006                 // Remove 'checked' from sanitized autofill request.
1007                 writtenFlags = flags & ~FLAGS_CHECKED;
1008             }
1009             if (mAutofillOverlay != null) {
1010                 if (mAutofillOverlay.focused) {
1011                     writtenFlags |= ViewNode.FLAGS_FOCUSED;
1012                 } else {
1013                     writtenFlags &= ~ViewNode.FLAGS_FOCUSED;
1014                 }
1015             }
1016 
1017             out.writeInt(writtenFlags);
1018             out.writeInt(autofillFlags);
1019             if ((flags&FLAGS_HAS_ID) != 0) {
1020                 out.writeInt(mId);
1021                 if (mId != View.NO_ID) {
1022                     writeString(out, pwriter, mIdEntry);
1023                     if (mIdEntry != null) {
1024                         writeString(out, pwriter, mIdType);
1025                         writeString(out, pwriter, mIdPackage);
1026                     }
1027                 }
1028             }
1029 
1030             if (autofillFlags != 0) {
1031                 out.writeInt(mSanitized ? 1 : 0);
1032                 out.writeInt(mImportantForAutofill);
1033                 writeSensitive = mSanitized || !sanitizeOnWrite;
1034                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID) != 0) {
1035                     out.writeInt(mAutofillId.getViewId());
1036                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID) != 0) {
1037                         out.writeInt(mAutofillId.getVirtualChildIntId());
1038                     }
1039                     if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_SESSION_ID) != 0) {
1040                         out.writeInt(mAutofillId.getSessionId());
1041                     }
1042                 }
1043                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
1044                     out.writeInt(mAutofillType);
1045                 }
1046                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS) != 0) {
1047                     out.writeStringArray(mAutofillHints);
1048                 }
1049                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE) != 0) {
1050                     final AutofillValue sanitizedValue;
1051                     if (writeSensitive) {
1052                         sanitizedValue = mAutofillValue;
1053                     } else if (mAutofillOverlay != null && mAutofillOverlay.value != null) {
1054                         sanitizedValue = mAutofillOverlay.value;
1055                     } else {
1056                         sanitizedValue = null;
1057                     }
1058                     out.writeParcelable(sanitizedValue, 0);
1059                 }
1060                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
1061                     out.writeCharSequenceArray(mAutofillOptions);
1062                 }
1063                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HTML_INFO) != 0) {
1064                     out.writeParcelable((Parcelable) mHtmlInfo, 0);
1065                 }
1066                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS) != 0) {
1067                     out.writeInt(mMinEms);
1068                 }
1069                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS) != 0) {
1070                     out.writeInt(mMaxEms);
1071                 }
1072                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
1073                     out.writeInt(mMaxLength);
1074                 }
1075                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
1076                     writeString(out, pwriter, mTextIdEntry);
1077                 }
1078                 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY) != 0) {
1079                     writeString(out, pwriter, mHintIdEntry);
1080                 }
1081             }
1082             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
1083                 out.writeInt(mX);
1084                 out.writeInt(mY);
1085                 out.writeInt(mWidth);
1086                 out.writeInt(mHeight);
1087             } else {
1088                 out.writeInt((mY<<16) | mX);
1089                 out.writeInt((mHeight<<16) | mWidth);
1090             }
1091             if ((flags&FLAGS_HAS_SCROLL) != 0) {
1092                 out.writeInt(mScrollX);
1093                 out.writeInt(mScrollY);
1094             }
1095             if ((flags&FLAGS_HAS_MATRIX) != 0) {
1096                 if (tmpMatrix == null) {
1097                     tmpMatrix = new float[9];
1098                 }
1099                 mMatrix.getValues(tmpMatrix);
1100                 out.writeFloatArray(tmpMatrix);
1101             }
1102             if ((flags&FLAGS_HAS_ELEVATION) != 0) {
1103                 out.writeFloat(mElevation);
1104             }
1105             if ((flags&FLAGS_HAS_ALPHA) != 0) {
1106                 out.writeFloat(mAlpha);
1107             }
1108             if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
1109                 TextUtils.writeToParcel(mContentDescription, out, 0);
1110             }
1111             if ((flags&FLAGS_HAS_TEXT) != 0) {
1112                 mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0, writeSensitive);
1113             }
1114             if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
1115                 out.writeInt(mInputType);
1116             }
1117             if ((flags & FLAGS_HAS_URL_SCHEME) != 0) {
1118                 out.writeString(mWebScheme);
1119             }
1120             if ((flags&FLAGS_HAS_URL_DOMAIN) != 0) {
1121                 out.writeString(mWebDomain);
1122             }
1123             if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) {
1124                 out.writeParcelable(mLocaleList, 0);
1125             }
1126             if ((flags & FLAGS_HAS_MIME_TYPES) != 0) {
1127                 out.writeStringArray(mReceiveContentMimeTypes);
1128             }
1129             if ((flags&FLAGS_HAS_EXTRAS) != 0) {
1130                 out.writeBundle(mExtras);
1131             }
1132             return flags;
1133         }
1134 
1135         /**
1136          * Returns the ID associated with this view, as per {@link View#getId() View.getId()}.
1137          */
getId()1138         public int getId() {
1139             return mId;
1140         }
1141 
1142         /**
1143          * If {@link #getId()} is a resource identifier, this is the package name of that
1144          * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
1145          * for more information.
1146          */
1147         @Nullable
getIdPackage()1148         public String getIdPackage() {
1149             return mIdPackage;
1150         }
1151 
1152         /**
1153          * If {@link #getId()} is a resource identifier, this is the type name of that
1154          * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
1155          * for more information.
1156          */
1157         @Nullable
getIdType()1158         public String getIdType() {
1159             return mIdType;
1160         }
1161 
1162         /**
1163          * If {@link #getId()} is a resource identifier, this is the entry name of that
1164          * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
1165          * for more information.
1166          */
1167         @Nullable
getIdEntry()1168         public String getIdEntry() {
1169             return mIdEntry;
1170         }
1171 
1172         /**
1173          * Gets the id that can be used to autofill the view contents.
1174          *
1175          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
1176          *
1177          * @return id that can be used to autofill the view contents, or {@code null} if the
1178          * structure was created for assist purposes.
1179          */
getAutofillId()1180         @Nullable public AutofillId getAutofillId() {
1181             return mAutofillId;
1182         }
1183 
1184         /**
1185          * Gets the type of value that can be used to autofill the view contents.
1186          *
1187          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
1188          *
1189          * @return autofill type as defined by {@link View#getAutofillType()},
1190          * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for assist purposes.
1191          */
getAutofillType()1192         public @View.AutofillType int getAutofillType() {
1193             return mAutofillType;
1194         }
1195 
1196         /**
1197          * Describes the content of a view so that a autofill service can fill in the appropriate
1198          * data.
1199          *
1200          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1201          * not for Assist - see {@link View#getAutofillHints()} for more info.
1202          *
1203          * @return The autofill hints for this view, or {@code null} if the structure was created
1204          * for assist purposes.
1205          */
getAutofillHints()1206         @Nullable public String[] getAutofillHints() {
1207             return mAutofillHints;
1208         }
1209 
1210         /**
1211          * Gets the value of this view.
1212          *
1213          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1214          * not for assist purposes.
1215          *
1216          * @return the autofill value of this view, or {@code null} if the structure was created
1217          * for assist purposes.
1218          */
getAutofillValue()1219         @Nullable public AutofillValue getAutofillValue() {
1220             return mAutofillValue;
1221         }
1222 
1223         /** @hide **/
setAutofillOverlay(AutofillOverlay overlay)1224         public void setAutofillOverlay(AutofillOverlay overlay) {
1225             mAutofillOverlay = overlay;
1226         }
1227 
1228         /**
1229          * Gets the options that can be used to autofill this view.
1230          *
1231          * <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate
1232          * the meaning of each possible value in the list.
1233          *
1234          * <p>It's relevant when the {@link AssistStructure} is used for autofill purposes, not
1235          * for assist purposes.
1236          *
1237          * @return the options that can be used to autofill this view, or {@code null} if the
1238          * structure was created for assist purposes.
1239          */
getAutofillOptions()1240         @Nullable public CharSequence[] getAutofillOptions() {
1241             return mAutofillOptions;
1242         }
1243 
1244         /**
1245          * Gets the {@link android.text.InputType} bits of this structure.
1246          *
1247          * @return bits as defined by {@link android.text.InputType}.
1248          */
getInputType()1249         public int getInputType() {
1250             return mInputType;
1251         }
1252 
1253         /** @hide */
isSanitized()1254         public boolean isSanitized() {
1255             return mSanitized;
1256         }
1257 
1258         /**
1259          * Updates the {@link AutofillValue} of this structure.
1260          *
1261          * <p>Should be used just before sending the structure to the
1262          * {@link android.service.autofill.AutofillService} for saving, since it will override the
1263          * initial value.
1264          *
1265          * @hide
1266          */
updateAutofillValue(AutofillValue value)1267         public void updateAutofillValue(AutofillValue value) {
1268             mAutofillValue = value;
1269             if (value.isText()) {
1270                 if (mText == null) {
1271                     mText = new ViewNodeText();
1272                 }
1273                 mText.mText = value.getTextValue();
1274             }
1275         }
1276 
1277         /**
1278          * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
1279          */
getLeft()1280         public int getLeft() {
1281             return mX;
1282         }
1283 
1284         /**
1285          * Returns the top edge of this view, in pixels, relative to the top edge of its parent.
1286          */
getTop()1287         public int getTop() {
1288             return mY;
1289         }
1290 
1291         /**
1292          * Returns the current X scroll offset of this view, as per
1293          * {@link android.view.View#getScrollX() View.getScrollX()}.
1294          */
getScrollX()1295         public int getScrollX() {
1296             return mScrollX;
1297         }
1298 
1299         /**
1300          * Returns the current Y scroll offset of this view, as per
1301          * {@link android.view.View#getScrollX() View.getScrollY()}.
1302          */
getScrollY()1303         public int getScrollY() {
1304             return mScrollY;
1305         }
1306 
1307         /**
1308          * Returns the width of this view, in pixels.
1309          */
getWidth()1310         public int getWidth() {
1311             return mWidth;
1312         }
1313 
1314         /**
1315          * Returns the height of this view, in pixels.
1316          */
getHeight()1317         public int getHeight() {
1318             return mHeight;
1319         }
1320 
1321         /**
1322          * Returns the transformation that has been applied to this view, such as a translation
1323          * or scaling.  The returned Matrix object is owned by ViewNode; do not modify it.
1324          * Returns null if there is no transformation applied to the view.
1325          *
1326          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1327          * not for autofill purposes.
1328          */
getTransformation()1329         public Matrix getTransformation() {
1330             return mMatrix;
1331         }
1332 
1333         /**
1334          * Returns the visual elevation of the view, used for shadowing and other visual
1335          * characterstics, as set by {@link ViewStructure#setElevation
1336          * ViewStructure.setElevation(float)}.
1337          *
1338          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1339          * not for autofill purposes.
1340          */
getElevation()1341         public float getElevation() {
1342             return mElevation;
1343         }
1344 
1345         /**
1346          * Returns the alpha transformation of the view, used to reduce the overall opacity
1347          * of the view's contents, as set by {@link ViewStructure#setAlpha
1348          * ViewStructure.setAlpha(float)}.
1349          *
1350          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1351          * not for autofill purposes.
1352          */
getAlpha()1353         public float getAlpha() {
1354             return mAlpha;
1355         }
1356 
1357         /**
1358          * Returns the visibility mode of this view, as per
1359          * {@link android.view.View#getVisibility() View.getVisibility()}.
1360          */
getVisibility()1361         public int getVisibility() {
1362             return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
1363         }
1364 
1365         /**
1366          * Returns true if assist data has been blocked starting at this node in the hierarchy.
1367          */
isAssistBlocked()1368         public boolean isAssistBlocked() {
1369             return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) != 0;
1370         }
1371 
1372         /**
1373          * Returns true if this node is in an enabled state.
1374          */
isEnabled()1375         public boolean isEnabled() {
1376             return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
1377         }
1378 
1379         /**
1380          * Returns true if this node is clickable by the user.
1381          */
isClickable()1382         public boolean isClickable() {
1383             return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
1384         }
1385 
1386         /**
1387          * Returns true if this node can take input focus.
1388          */
isFocusable()1389         public boolean isFocusable() {
1390             return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
1391         }
1392 
1393         /**
1394          * Returns true if this node currently had input focus at the time that the
1395          * structure was collected.
1396          */
isFocused()1397         public boolean isFocused() {
1398             return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
1399         }
1400 
1401         /**
1402          * Returns true if this node currently had accessibility focus at the time that the
1403          * structure was collected.
1404          */
isAccessibilityFocused()1405         public boolean isAccessibilityFocused() {
1406             return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
1407         }
1408 
1409         /**
1410          * Returns true if this node represents something that is checkable by the user.
1411          */
isCheckable()1412         public boolean isCheckable() {
1413             return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
1414         }
1415 
1416         /**
1417          * Returns true if this node is currently in a checked state.
1418          */
isChecked()1419         public boolean isChecked() {
1420             return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
1421         }
1422 
1423         /**
1424          * Returns true if this node has currently been selected by the user.
1425          */
isSelected()1426         public boolean isSelected() {
1427             return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
1428         }
1429 
1430         /**
1431          * Returns true if this node has currently been activated by the user.
1432          */
isActivated()1433         public boolean isActivated() {
1434             return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
1435         }
1436 
1437         /**
1438          * Returns true if this node is opaque.
1439          */
isOpaque()1440         public boolean isOpaque() { return (mFlags&ViewNode.FLAGS_OPAQUE) != 0; }
1441 
1442         /**
1443          * Returns true if this node is something the user can perform a long click/press on.
1444          */
isLongClickable()1445         public boolean isLongClickable() {
1446             return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
1447         }
1448 
1449         /**
1450          * Returns true if this node is something the user can perform a context click on.
1451          */
isContextClickable()1452         public boolean isContextClickable() {
1453             return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
1454         }
1455 
1456         /**
1457          * Returns the class name of the node's implementation, indicating its behavior.
1458          * For example, a button will report "android.widget.Button" meaning it behaves
1459          * like a {@link android.widget.Button}.
1460          */
1461         @Nullable
getClassName()1462         public String getClassName() {
1463             return mClassName;
1464         }
1465 
1466         /**
1467          * Returns any content description associated with the node, which semantically describes
1468          * its purpose for accessibility and other uses.
1469          */
1470         @Nullable
getContentDescription()1471         public CharSequence getContentDescription() {
1472             return mContentDescription;
1473         }
1474 
1475         /**
1476          * Returns the domain of the HTML document represented by this view.
1477          *
1478          * <p>Typically used when the view associated with the view is a container for an HTML
1479          * document.
1480          *
1481          * <p><b>Warning:</b> an autofill service cannot trust the value reported by this method
1482          * without verifing its authenticity&mdash;see the "Web security" section of
1483          * {@link android.service.autofill.AutofillService} for more details.
1484          *
1485          * @return domain-only part of the document. For example, if the full URL is
1486          * {@code https://example.com/login?user=my_user}, it returns {@code example.com}.
1487          */
getWebDomain()1488         @Nullable public String getWebDomain() {
1489             return mWebDomain;
1490         }
1491 
1492         /**
1493          * @hide
1494          */
setWebDomain(@ullable String domain)1495         public void setWebDomain(@Nullable String domain) {
1496             if (domain == null) return;
1497 
1498             Uri uri = Uri.parse(domain);
1499             if (uri == null) {
1500                 // Cannot log domain because it could contain PII;
1501                 Log.w(TAG, "Failed to parse web domain");
1502                 return;
1503             }
1504 
1505             mWebScheme = uri.getScheme();
1506             if (mWebScheme == null) {
1507                 uri = Uri.parse("http://" + domain);
1508             }
1509 
1510             mWebDomain = uri.getHost();
1511         }
1512 
1513         /**
1514          * Returns the scheme of the HTML document represented by this view.
1515          *
1516          * <p>Typically used when the view associated with the view is a container for an HTML
1517          * document.
1518          *
1519          * @return scheme-only part of the document. For example, if the full URL is
1520          * {@code https://example.com/login?user=my_user}, it returns {@code https}.
1521          */
getWebScheme()1522         @Nullable public String getWebScheme() {
1523             return mWebScheme;
1524         }
1525 
1526         /**
1527          * Returns the HTML properties associated with this view.
1528          *
1529          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1530          * not for assist purposes.
1531          *
1532          * @return the HTML properties associated with this view, or {@code null} if the
1533          * structure was created for assist purposes.
1534          */
getHtmlInfo()1535         @Nullable public HtmlInfo getHtmlInfo() {
1536             return mHtmlInfo;
1537         }
1538 
1539         /**
1540          * Returns the list of locales associated with this view.
1541          */
getLocaleList()1542         @Nullable public LocaleList getLocaleList() {
1543             return mLocaleList;
1544         }
1545 
1546         /**
1547          * Returns the MIME types accepted by {@link View#performReceiveContent} for this view. See
1548          * {@link View#getReceiveContentMimeTypes()} for details.
1549          */
1550         @Nullable
1551         @SuppressLint("NullableCollection")
getReceiveContentMimeTypes()1552         public String[] getReceiveContentMimeTypes() {
1553             return mReceiveContentMimeTypes;
1554         }
1555 
1556         /**
1557          * Returns any text associated with the node that is displayed to the user, or null
1558          * if there is none.
1559          */
1560         @Nullable
getText()1561         public CharSequence getText() {
1562             return mText != null ? mText.mText : null;
1563         }
1564 
1565         /**
1566          * If {@link #getText()} is non-null, this is where the current selection starts.
1567          *
1568          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1569          * not for autofill purposes.
1570          */
getTextSelectionStart()1571         public int getTextSelectionStart() {
1572             return mText != null ? mText.mTextSelectionStart : -1;
1573         }
1574 
1575         /**
1576          * If {@link #getText()} is non-null, this is where the current selection starts.
1577          * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
1578          * indicating the cursor position.
1579          *
1580          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1581          * not for autofill purposes.
1582          */
getTextSelectionEnd()1583         public int getTextSelectionEnd() {
1584             return mText != null ? mText.mTextSelectionEnd : -1;
1585         }
1586 
1587         /**
1588          * If {@link #getText()} is non-null, this is the main text color associated with it.
1589          * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
1590          * Note that the text may also contain style spans that modify the color of specific
1591          * parts of the text.
1592          */
getTextColor()1593         public int getTextColor() {
1594             return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
1595         }
1596 
1597         /**
1598          * If {@link #getText()} is non-null, this is the main text background color associated
1599          * with it.
1600          * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
1601          * Note that the text may also contain style spans that modify the color of specific
1602          * parts of the text.
1603          *
1604          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1605          * not for autofill purposes.
1606          */
getTextBackgroundColor()1607         public int getTextBackgroundColor() {
1608             return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
1609         }
1610 
1611         /**
1612          * If {@link #getText()} is non-null, this is the main text size (in pixels) associated
1613          * with it.
1614          * Note that the text may also contain style spans that modify the size of specific
1615          * parts of the text.
1616          *
1617          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1618          * not for autofill purposes.
1619          */
getTextSize()1620         public float getTextSize() {
1621             return mText != null ? mText.mTextSize : 0;
1622         }
1623 
1624         /**
1625          * If {@link #getText()} is non-null, this is the main text style associated
1626          * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
1627          * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
1628          * {@link #TEXT_STYLE_UNDERLINE}.
1629          * Note that the text may also contain style spans that modify the style of specific
1630          * parts of the text.
1631          *
1632          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1633          * not for autofill purposes.
1634          */
getTextStyle()1635         public int getTextStyle() {
1636             return mText != null ? mText.mTextStyle : 0;
1637         }
1638 
1639         /**
1640          * Return per-line offsets into the text returned by {@link #getText()}.  Each entry
1641          * in the array is a formatted line of text, and the value it contains is the offset
1642          * into the text string where that line starts.  May return null if there is no line
1643          * information.
1644          *
1645          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1646          * not for autofill purposes.
1647          */
1648         @Nullable
getTextLineCharOffsets()1649         public int[] getTextLineCharOffsets() {
1650             return mText != null ? mText.mLineCharOffsets : null;
1651         }
1652 
1653         /**
1654          * Return per-line baselines into the text returned by {@link #getText()}.  Each entry
1655          * in the array is a formatted line of text, and the value it contains is the baseline
1656          * where that text appears in the view.  May return null if there is no line
1657          * information.
1658          *
1659          * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1660          * not for autofill purposes.
1661          */
1662         @Nullable
getTextLineBaselines()1663         public int[] getTextLineBaselines() {
1664             return mText != null ? mText.mLineBaselines : null;
1665         }
1666 
1667         /**
1668          * Gets the identifier used to set the text associated with this view.
1669          *
1670          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1671          * not for assist purposes.
1672          */
1673         @Nullable
getTextIdEntry()1674         public String getTextIdEntry() {
1675             return mTextIdEntry;
1676         }
1677 
1678         /**
1679          * Return additional hint text associated with the node; this is typically used with
1680          * a node that takes user input, describing to the user what the input means.
1681          */
1682         @Nullable
getHint()1683         public String getHint() {
1684             return mText != null ? mText.mHint : null;
1685         }
1686 
1687         /**
1688          * Gets the identifier used to set the hint associated with this view.
1689          *
1690          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1691          * not for assist purposes.
1692          */
1693         @Nullable
getHintIdEntry()1694         public String getHintIdEntry() {
1695             return mHintIdEntry;
1696         }
1697 
1698         /**
1699          * Return a Bundle containing optional vendor-specific extension information.
1700          */
1701         @Nullable
getExtras()1702         public Bundle getExtras() {
1703             return mExtras;
1704         }
1705 
1706         /**
1707          * Return the number of children this node has.
1708          */
getChildCount()1709         public int getChildCount() {
1710             return mChildren != null ? mChildren.length : 0;
1711         }
1712 
1713         /**
1714          * Return a child of this node, given an index value from 0 to
1715          * {@link #getChildCount()}-1.
1716          */
getChildAt(int index)1717         public ViewNode getChildAt(int index) {
1718             return mChildren[index];
1719         }
1720 
1721         /**
1722          * Returns the minimum width in ems of the text associated with this node, or {@code -1}
1723          * if not supported by the node.
1724          *
1725          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1726          * not for assist purposes.
1727          */
getMinTextEms()1728         public int getMinTextEms() {
1729             return mMinEms;
1730         }
1731 
1732         /**
1733          * Returns the maximum width in ems of the text associated with this node, or {@code -1}
1734          * if not supported by the node.
1735          *
1736          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1737          * not for assist purposes.
1738          */
getMaxTextEms()1739         public int getMaxTextEms() {
1740             return mMaxEms;
1741         }
1742 
1743         /**
1744          * Returns the maximum length of the text associated with this node, or {@code -1} if not
1745          * supported by the node or not set. System may set a default value if the text length is
1746          * not set.
1747          *
1748          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1749          * not for assist purposes.
1750          */
getMaxTextLength()1751         public int getMaxTextLength() {
1752             return mMaxLength;
1753         }
1754 
1755         /**
1756          * Gets the {@link View#setImportantForAutofill(int) importantForAutofill mode} of
1757          * the view associated with this node.
1758          *
1759          * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
1760          */
getImportantForAutofill()1761         public @AutofillImportance int getImportantForAutofill() {
1762             return mImportantForAutofill;
1763         }
1764     }
1765 
1766     /**
1767      * A parcelable wrapper class around {@link ViewNode}.
1768      *
1769      * <p>This class, when parceled and unparceled, does not carry the child nodes.
1770      *
1771      * @hide
1772      */
1773     public static final class ViewNodeParcelable implements Parcelable {
1774 
1775         @NonNull
1776         private final ViewNode mViewNode;
1777 
ViewNodeParcelable(@onNull ViewNode viewNode)1778         public ViewNodeParcelable(@NonNull ViewNode viewNode) {
1779             mViewNode = viewNode;
1780         }
1781 
ViewNodeParcelable(@onNull Parcel in)1782         public ViewNodeParcelable(@NonNull Parcel in) {
1783             mViewNode = new ViewNode(in);
1784         }
1785 
1786         @NonNull
getViewNode()1787         public ViewNode getViewNode() {
1788             return mViewNode;
1789         }
1790 
1791         @Override
describeContents()1792         public int describeContents() {
1793             return 0;
1794         }
1795 
1796         @Override
writeToParcel(@onNull Parcel parcel, int flags)1797         public void writeToParcel(@NonNull Parcel parcel, int flags) {
1798             mViewNode.writeSelfToParcel(parcel, /*pwriter=*/null, /*sanitizeOnWrite=*/false,
1799                     /*tmpMatrix*/null, /*willWriteChildren=*/ false);
1800         }
1801 
1802         @NonNull
1803         public static final Parcelable.Creator<ViewNodeParcelable> CREATOR =
1804                 new Parcelable.Creator<ViewNodeParcelable>() {
1805                     @Override
1806                     public ViewNodeParcelable createFromParcel(@NonNull Parcel in) {
1807                         return new ViewNodeParcelable(in);
1808                     }
1809 
1810                     @Override
1811                     public ViewNodeParcelable[] newArray(int size) {
1812                         return new ViewNodeParcelable[size];
1813                     }
1814                 };
1815     }
1816 
1817     /**
1818      * POJO used to override some autofill-related values when the node is parcelized.
1819      *
1820      * @hide
1821      */
1822     static public class AutofillOverlay {
1823         public boolean focused;
1824         public AutofillValue value;
1825     }
1826 
1827     /**
1828      * @hide
1829      */
1830     public static class ViewNodeBuilder extends ViewStructure {
1831         final AssistStructure mAssist;
1832         final ViewNode mNode;
1833         final boolean mAsync;
1834 
1835         /**
1836          * Used to instantiate a builder for a stand-alone {@link ViewNode} which is not associated
1837          * to a properly created {@link AssistStructure}.
1838          */
ViewNodeBuilder()1839         public ViewNodeBuilder() {
1840             mAssist = new AssistStructure();
1841             mNode = new ViewNode();
1842             mAsync = false;
1843         }
1844 
ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async)1845         ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
1846             mAssist = assist;
1847             mNode = node;
1848             mAsync = async;
1849         }
1850 
1851         @NonNull
getViewNode()1852         public ViewNode getViewNode() {
1853             return mNode;
1854         }
1855 
1856         @Override
setId(int id, String packageName, String typeName, String entryName)1857         public void setId(int id, String packageName, String typeName, String entryName) {
1858             mNode.mId = id;
1859             mNode.mIdPackage = packageName;
1860             mNode.mIdType = typeName;
1861             mNode.mIdEntry = entryName;
1862         }
1863 
1864         @Override
setDimens(int left, int top, int scrollX, int scrollY, int width, int height)1865         public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
1866             mNode.mX = left;
1867             mNode.mY = top;
1868             mNode.mScrollX = scrollX;
1869             mNode.mScrollY = scrollY;
1870             mNode.mWidth = width;
1871             mNode.mHeight = height;
1872         }
1873 
1874         @Override
setTransformation(Matrix matrix)1875         public void setTransformation(Matrix matrix) {
1876             if (matrix == null) {
1877                 mNode.mMatrix = null;
1878             } else {
1879                 mNode.mMatrix = new Matrix(matrix);
1880             }
1881         }
1882 
1883         @Override
setElevation(float elevation)1884         public void setElevation(float elevation) {
1885             mNode.mElevation = elevation;
1886         }
1887 
1888         @Override
setAlpha(float alpha)1889         public void setAlpha(float alpha) {
1890             mNode.mAlpha = alpha;
1891         }
1892 
1893         @Override
setVisibility(int visibility)1894         public void setVisibility(int visibility) {
1895             mNode.mFlags = (mNode.mFlags & ~ViewNode.FLAGS_VISIBILITY_MASK)
1896                     | (visibility & ViewNode.FLAGS_VISIBILITY_MASK);
1897         }
1898 
1899         @Override
setAssistBlocked(boolean state)1900         public void setAssistBlocked(boolean state) {
1901             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED)
1902                     | (state ? ViewNode.FLAGS_ASSIST_BLOCKED : 0);
1903         }
1904 
1905         @Override
setEnabled(boolean state)1906         public void setEnabled(boolean state) {
1907             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED)
1908                     | (state ? 0 : ViewNode.FLAGS_DISABLED);
1909         }
1910 
1911         @Override
setClickable(boolean state)1912         public void setClickable(boolean state) {
1913             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE)
1914                     | (state ? ViewNode.FLAGS_CLICKABLE : 0);
1915         }
1916 
1917         @Override
setLongClickable(boolean state)1918         public void setLongClickable(boolean state) {
1919             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE)
1920                     | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0);
1921         }
1922 
1923         @Override
setContextClickable(boolean state)1924         public void setContextClickable(boolean state) {
1925             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE)
1926                     | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0);
1927         }
1928 
1929         @Override
setFocusable(boolean state)1930         public void setFocusable(boolean state) {
1931             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
1932                     | (state ? ViewNode.FLAGS_FOCUSABLE : 0);
1933         }
1934 
1935         @Override
setFocused(boolean state)1936         public void setFocused(boolean state) {
1937             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED)
1938                     | (state ? ViewNode.FLAGS_FOCUSED : 0);
1939         }
1940 
1941         @Override
setAccessibilityFocused(boolean state)1942         public void setAccessibilityFocused(boolean state) {
1943             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED)
1944                     | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0);
1945         }
1946 
1947         @Override
setCheckable(boolean state)1948         public void setCheckable(boolean state) {
1949             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE)
1950                     | (state ? ViewNode.FLAGS_CHECKABLE : 0);
1951         }
1952 
1953         @Override
setChecked(boolean state)1954         public void setChecked(boolean state) {
1955             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED)
1956                     | (state ? ViewNode.FLAGS_CHECKED : 0);
1957         }
1958 
1959         @Override
setSelected(boolean state)1960         public void setSelected(boolean state) {
1961             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED)
1962                     | (state ? ViewNode.FLAGS_SELECTED : 0);
1963         }
1964 
1965         @Override
setActivated(boolean state)1966         public void setActivated(boolean state) {
1967             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED)
1968                     | (state ? ViewNode.FLAGS_ACTIVATED : 0);
1969         }
1970 
1971         @Override
setOpaque(boolean opaque)1972         public void setOpaque(boolean opaque) {
1973             mNode.mFlags = (mNode.mFlags & ~ViewNode.FLAGS_OPAQUE)
1974                     | (opaque ? ViewNode.FLAGS_OPAQUE : 0);
1975         }
1976 
1977         @Override
setClassName(String className)1978         public void setClassName(String className) {
1979             mNode.mClassName = className;
1980         }
1981 
1982         @Override
setContentDescription(CharSequence contentDescription)1983         public void setContentDescription(CharSequence contentDescription) {
1984             mNode.mContentDescription = contentDescription;
1985         }
1986 
getNodeText()1987         private final ViewNodeText getNodeText() {
1988             if (mNode.mText != null) {
1989                 return mNode.mText;
1990             }
1991             mNode.mText = new ViewNodeText();
1992             return mNode.mText;
1993         }
1994 
1995         @Override
setText(CharSequence text)1996         public void setText(CharSequence text) {
1997             ViewNodeText t = getNodeText();
1998             t.mText = TextUtils.trimNoCopySpans(text);
1999             t.mTextSelectionStart = t.mTextSelectionEnd = -1;
2000         }
2001 
2002         @Override
setText(CharSequence text, int selectionStart, int selectionEnd)2003         public void setText(CharSequence text, int selectionStart, int selectionEnd) {
2004             ViewNodeText t = getNodeText();
2005             t.mText = TextUtils.trimNoCopySpans(text);
2006             t.mTextSelectionStart = selectionStart;
2007             t.mTextSelectionEnd = selectionEnd;
2008         }
2009 
2010         @Override
setTextStyle(float size, int fgColor, int bgColor, int style)2011         public void setTextStyle(float size, int fgColor, int bgColor, int style) {
2012             ViewNodeText t = getNodeText();
2013             t.mTextColor = fgColor;
2014             t.mTextBackgroundColor = bgColor;
2015             t.mTextSize = size;
2016             t.mTextStyle = style;
2017         }
2018 
2019         @Override
setTextLines(int[] charOffsets, int[] baselines)2020         public void setTextLines(int[] charOffsets, int[] baselines) {
2021             ViewNodeText t = getNodeText();
2022             t.mLineCharOffsets = charOffsets;
2023             t.mLineBaselines = baselines;
2024         }
2025 
2026         @Override
setTextIdEntry(@onNull String entryName)2027         public void setTextIdEntry(@NonNull String entryName) {
2028             mNode.mTextIdEntry = Objects.requireNonNull(entryName);
2029         }
2030 
2031         @Override
setHint(CharSequence hint)2032         public void setHint(CharSequence hint) {
2033             getNodeText().mHint = hint != null ? hint.toString() : null;
2034         }
2035 
2036         @Override
setHintIdEntry(@onNull String entryName)2037         public void setHintIdEntry(@NonNull String entryName) {
2038             mNode.mHintIdEntry = Objects.requireNonNull(entryName);
2039         }
2040 
2041         @Override
getText()2042         public CharSequence getText() {
2043             return mNode.mText != null ? mNode.mText.mText : null;
2044         }
2045 
2046         @Override
getTextSelectionStart()2047         public int getTextSelectionStart() {
2048             return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1;
2049         }
2050 
2051         @Override
getTextSelectionEnd()2052         public int getTextSelectionEnd() {
2053             return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1;
2054         }
2055 
2056         @Override
getHint()2057         public CharSequence getHint() {
2058             return mNode.mText != null ? mNode.mText.mHint : null;
2059         }
2060 
2061         @Override
getExtras()2062         public Bundle getExtras() {
2063             if (mNode.mExtras != null) {
2064                 return mNode.mExtras;
2065             }
2066             mNode.mExtras = new Bundle();
2067             return mNode.mExtras;
2068         }
2069 
2070         @Override
hasExtras()2071         public boolean hasExtras() {
2072             return mNode.mExtras != null;
2073         }
2074 
2075         @Override
setChildCount(int num)2076         public void setChildCount(int num) {
2077             mNode.mChildren = new ViewNode[num];
2078         }
2079 
2080         @Override
addChildCount(int num)2081         public int addChildCount(int num) {
2082             if (mNode.mChildren == null) {
2083                 setChildCount(num);
2084                 return 0;
2085             }
2086             final int start = mNode.mChildren.length;
2087             ViewNode[] newArray = new ViewNode[start + num];
2088             System.arraycopy(mNode.mChildren, 0, newArray, 0, start);
2089             mNode.mChildren = newArray;
2090             return start;
2091         }
2092 
2093         @Override
getChildCount()2094         public int getChildCount() {
2095             return mNode.mChildren != null ? mNode.mChildren.length : 0;
2096         }
2097 
2098         @Override
newChild(int index)2099         public ViewStructure newChild(int index) {
2100             ViewNode node = new ViewNode();
2101             mNode.mChildren[index] = node;
2102             return new ViewNodeBuilder(mAssist, node, false);
2103         }
2104 
2105         @Override
asyncNewChild(int index)2106         public ViewStructure asyncNewChild(int index) {
2107             synchronized (mAssist) {
2108                 ViewNode node = new ViewNode();
2109                 mNode.mChildren[index] = node;
2110                 ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
2111                 mAssist.mPendingAsyncChildren.add(builder);
2112                 return builder;
2113             }
2114         }
2115 
2116         @Override
asyncCommit()2117         public void asyncCommit() {
2118             synchronized (mAssist) {
2119                 if (!mAsync) {
2120                     throw new IllegalStateException("Child " + this
2121                             + " was not created with ViewStructure.asyncNewChild");
2122                 }
2123                 if (!mAssist.mPendingAsyncChildren.remove(this)) {
2124                     throw new IllegalStateException("Child " + this + " already committed");
2125                 }
2126                 mAssist.notifyAll();
2127             }
2128         }
2129 
2130         @Override
getTempRect()2131         public Rect getTempRect() {
2132             return mAssist.mTmpRect;
2133         }
2134 
2135         @Override
setAutofillId(@onNull AutofillId id)2136         public void setAutofillId(@NonNull AutofillId id) {
2137             mNode.mAutofillId = id;
2138         }
2139 
2140         @Override
setAutofillId(@onNull AutofillId parentId, int virtualId)2141         public void setAutofillId(@NonNull AutofillId parentId, int virtualId) {
2142             mNode.mAutofillId = new AutofillId(parentId, virtualId);
2143         }
2144 
2145         @Override
getAutofillId()2146         public AutofillId getAutofillId() {
2147             return mNode.mAutofillId;
2148         }
2149 
2150         @Override
setAutofillType(@iew.AutofillType int type)2151         public void setAutofillType(@View.AutofillType int type) {
2152             mNode.mAutofillType = type;
2153         }
2154 
2155         @Override
setAutofillHints(@ullable String[] hints)2156         public void setAutofillHints(@Nullable String[] hints) {
2157             mNode.mAutofillHints = hints;
2158         }
2159 
2160         @Override
setAutofillValue(AutofillValue value)2161         public void setAutofillValue(AutofillValue value) {
2162             mNode.mAutofillValue = value;
2163         }
2164 
2165         @Override
setAutofillOptions(CharSequence[] options)2166         public void setAutofillOptions(CharSequence[] options) {
2167             mNode.mAutofillOptions = options;
2168         }
2169 
2170         @Override
setImportantForAutofill(@utofillImportance int mode)2171         public void setImportantForAutofill(@AutofillImportance int mode) {
2172             mNode.mImportantForAutofill = mode;
2173         }
2174 
2175         @Override
setReceiveContentMimeTypes(@ullable String[] mimeTypes)2176         public void setReceiveContentMimeTypes(@Nullable String[] mimeTypes) {
2177             mNode.mReceiveContentMimeTypes = mimeTypes;
2178         }
2179 
2180         @Override
setInputType(int inputType)2181         public void setInputType(int inputType) {
2182             mNode.mInputType = inputType;
2183         }
2184 
2185         @Override
setMinTextEms(int minEms)2186         public void setMinTextEms(int minEms) {
2187             mNode.mMinEms = minEms;
2188         }
2189 
2190         @Override
setMaxTextEms(int maxEms)2191         public void setMaxTextEms(int maxEms) {
2192             mNode.mMaxEms = maxEms;
2193         }
2194 
2195         @Override
setMaxTextLength(int maxLength)2196         public void setMaxTextLength(int maxLength) {
2197             mNode.mMaxLength = maxLength;
2198         }
2199 
2200         @Override
setDataIsSensitive(boolean sensitive)2201         public void setDataIsSensitive(boolean sensitive) {
2202             mNode.mSanitized = !sensitive;
2203         }
2204 
2205         @Override
setWebDomain(@ullable String domain)2206         public void setWebDomain(@Nullable String domain) {
2207             mNode.setWebDomain(domain);
2208         }
2209 
2210         @Override
setLocaleList(LocaleList localeList)2211         public void setLocaleList(LocaleList localeList) {
2212             mNode.mLocaleList = localeList;
2213         }
2214 
2215         @Override
newHtmlInfoBuilder(@onNull String tagName)2216         public HtmlInfo.Builder newHtmlInfoBuilder(@NonNull String tagName) {
2217             return new HtmlInfoNodeBuilder(tagName);
2218         }
2219 
2220         @Override
setHtmlInfo(@onNull HtmlInfo htmlInfo)2221         public void setHtmlInfo(@NonNull HtmlInfo htmlInfo) {
2222             mNode.mHtmlInfo = htmlInfo;
2223         }
2224     }
2225 
2226     private static final class HtmlInfoNode extends HtmlInfo implements Parcelable {
2227         private final String mTag;
2228         private final String[] mNames;
2229         private final String[] mValues;
2230 
2231         // Not parcelable
2232         private ArrayList<Pair<String, String>> mAttributes;
2233 
HtmlInfoNode(HtmlInfoNodeBuilder builder)2234         private HtmlInfoNode(HtmlInfoNodeBuilder builder) {
2235             mTag = builder.mTag;
2236             if (builder.mNames == null) {
2237                 mNames = null;
2238                 mValues = null;
2239             } else {
2240                 mNames = new String[builder.mNames.size()];
2241                 mValues = new String[builder.mValues.size()];
2242                 builder.mNames.toArray(mNames);
2243                 builder.mValues.toArray(mValues);
2244             }
2245         }
2246 
2247         @Override
getTag()2248         public String getTag() {
2249             return mTag;
2250         }
2251 
2252         @Override
getAttributes()2253         public List<Pair<String, String>> getAttributes() {
2254             if (mAttributes == null && mNames != null) {
2255                 mAttributes = new ArrayList<>(mNames.length);
2256                 for (int i = 0; i < mNames.length; i++) {
2257                     final Pair<String, String> pair = new Pair<>(mNames[i], mValues[i]);
2258                     mAttributes.add(i, pair);
2259                 }
2260             }
2261             return mAttributes;
2262         }
2263 
2264         @Override
describeContents()2265         public int describeContents() {
2266             return 0;
2267         }
2268 
2269         @Override
writeToParcel(Parcel parcel, int flags)2270         public void writeToParcel(Parcel parcel, int flags) {
2271             parcel.writeString(mTag);
2272             parcel.writeStringArray(mNames);
2273             parcel.writeStringArray(mValues);
2274         }
2275 
2276         @SuppressWarnings("hiding")
2277         public static final @android.annotation.NonNull Creator<HtmlInfoNode> CREATOR = new Creator<HtmlInfoNode>() {
2278             @Override
2279             public HtmlInfoNode createFromParcel(Parcel parcel) {
2280                 // Always go through the builder to ensure the data ingested by
2281                 // the system obeys the contract of the builder to avoid attacks
2282                 // using specially crafted parcels.
2283                 final String tag = parcel.readString();
2284                 final HtmlInfoNodeBuilder builder = new HtmlInfoNodeBuilder(tag);
2285                 final String[] names = parcel.readStringArray();
2286                 final String[] values = parcel.readStringArray();
2287                 if (names != null && values != null) {
2288                     if (names.length != values.length) {
2289                         Log.w(TAG, "HtmlInfo attributes mismatch: names=" + names.length
2290                                 + ", values=" + values.length);
2291                     } else {
2292                         for (int i = 0; i < names.length; i++) {
2293                             builder.addAttribute(names[i], values[i]);
2294                         }
2295                     }
2296                 }
2297                 return builder.build();
2298             }
2299 
2300             @Override
2301             public HtmlInfoNode[] newArray(int size) {
2302                 return new HtmlInfoNode[size];
2303             }
2304         };
2305     }
2306 
2307     private static final class HtmlInfoNodeBuilder extends HtmlInfo.Builder {
2308         private final String mTag;
2309         private ArrayList<String> mNames;
2310         private ArrayList<String> mValues;
2311 
HtmlInfoNodeBuilder(String tag)2312         HtmlInfoNodeBuilder(String tag) {
2313             mTag = tag;
2314         }
2315 
2316         @Override
addAttribute(String name, String value)2317         public Builder addAttribute(String name, String value) {
2318             if (mNames == null) {
2319                 mNames = new ArrayList<>();
2320                 mValues = new ArrayList<>();
2321             }
2322             mNames.add(name);
2323             mValues.add(value);
2324             return this;
2325         }
2326 
2327         @Override
build()2328         public HtmlInfoNode build() {
2329             return new HtmlInfoNode(this);
2330         }
2331     }
2332 
2333     /** @hide */
AssistStructure(Activity activity, boolean forAutoFill, int flags)2334     public AssistStructure(Activity activity, boolean forAutoFill, int flags) {
2335         mHaveData = true;
2336         mFlags = flags;
2337         ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
2338                 activity.getActivityToken());
2339         for (int i=0; i<views.size(); i++) {
2340             ViewRootImpl root = views.get(i);
2341             if (root.getView() == null) {
2342                 Log.w(TAG, "Skipping window with dettached view: " + root.getTitle());
2343                 continue;
2344             }
2345             mWindowNodes.add(new WindowNode(this, root, forAutoFill, flags));
2346         }
2347     }
2348 
AssistStructure()2349     public AssistStructure() {
2350         mHaveData = true;
2351         mFlags = 0;
2352     }
2353 
2354     /** @hide */
AssistStructure(Parcel in)2355     public AssistStructure(Parcel in) {
2356         mTaskId = in.readInt();
2357         mActivityComponent = ComponentName.readFromParcel(in);
2358         mIsHomeActivity = in.readInt() == 1;
2359         mReceiveChannel = in.readStrongBinder();
2360     }
2361 
2362     /**
2363      * Helper method used to sanitize the structure before it's written to a parcel.
2364      *
2365      * <p>Used just on autofill.
2366      * @hide
2367      */
sanitizeForParceling(boolean sanitize)2368     public void sanitizeForParceling(boolean sanitize) {
2369         mSanitizeOnWrite = sanitize;
2370     }
2371 
2372     /** @hide */
dump(boolean showSensitive)2373     public void dump(boolean showSensitive) {
2374         if (mActivityComponent == null) {
2375             Log.i(TAG, "dump(): calling ensureData() first");
2376             ensureData();
2377         }
2378         Log.i(TAG, "Task id: " + mTaskId);
2379         Log.i(TAG, "Activity: " + (mActivityComponent != null
2380                 ? mActivityComponent.flattenToShortString()
2381                 : null));
2382         Log.i(TAG, "Sanitize on write: " + mSanitizeOnWrite);
2383         Log.i(TAG, "Flags: " + mFlags);
2384         final int N = getWindowNodeCount();
2385         for (int i=0; i<N; i++) {
2386             WindowNode node = getWindowNodeAt(i);
2387             Log.i(TAG, "Window #" + i + " [" + node.getLeft() + "," + node.getTop()
2388                     + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getTitle());
2389             dump("  ", node.getRootViewNode(), showSensitive);
2390         }
2391     }
2392 
dump(String prefix, ViewNode node, boolean showSensitive)2393     void dump(String prefix, ViewNode node, boolean showSensitive) {
2394         Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop()
2395                 + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName());
2396         int id = node.getId();
2397         if (id != 0) {
2398             StringBuilder sb = new StringBuilder();
2399             sb.append(prefix); sb.append("  ID: #"); sb.append(Integer.toHexString(id));
2400             String entry = node.getIdEntry();
2401             if (entry != null) {
2402                 String type = node.getIdType();
2403                 String pkg = node.getIdPackage();
2404                 sb.append(" "); sb.append(pkg); sb.append(":"); sb.append(type);
2405                 sb.append("/"); sb.append(entry);
2406             }
2407             Log.i(TAG, sb.toString());
2408         }
2409         int scrollX = node.getScrollX();
2410         int scrollY = node.getScrollY();
2411         if (scrollX != 0 || scrollY != 0) {
2412             Log.i(TAG, prefix + "  Scroll: " + scrollX + "," + scrollY);
2413         }
2414         Matrix matrix = node.getTransformation();
2415         if (matrix != null) {
2416             Log.i(TAG, prefix + "  Transformation: " + matrix);
2417         }
2418         float elevation = node.getElevation();
2419         if (elevation != 0) {
2420             Log.i(TAG, prefix + "  Elevation: " + elevation);
2421         }
2422         float alpha = node.getAlpha();
2423         if (alpha != 0) {
2424             Log.i(TAG, prefix + "  Alpha: " + elevation);
2425         }
2426         CharSequence contentDescription = node.getContentDescription();
2427         if (contentDescription != null) {
2428             Log.i(TAG, prefix + "  Content description: " + contentDescription);
2429         }
2430         CharSequence text = node.getText();
2431         if (text != null) {
2432             final String safeText = node.isSanitized() || showSensitive ? text.toString()
2433                     : "REDACTED[" + text.length() + " chars]";
2434             Log.i(TAG, prefix + "  Text (sel " + node.getTextSelectionStart() + "-"
2435                     + node.getTextSelectionEnd() + "): " + safeText);
2436             Log.i(TAG, prefix + "  Text size: " + node.getTextSize() + " , style: #"
2437                     + node.getTextStyle());
2438             Log.i(TAG, prefix + "  Text color fg: #" + Integer.toHexString(node.getTextColor())
2439                     + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
2440             Log.i(TAG, prefix + "  Input type: " + node.getInputType());
2441             Log.i(TAG, prefix + "  Resource id: " + node.getTextIdEntry());
2442         }
2443         String webDomain = node.getWebDomain();
2444         if (webDomain != null) {
2445             Log.i(TAG, prefix + "  Web domain: " + webDomain);
2446         }
2447         HtmlInfo htmlInfo = node.getHtmlInfo();
2448         if (htmlInfo != null) {
2449             Log.i(TAG, prefix + "  HtmlInfo: tag=" + htmlInfo.getTag()
2450                     + ", attr="+ htmlInfo.getAttributes());
2451         }
2452 
2453         LocaleList localeList = node.getLocaleList();
2454         if (localeList != null) {
2455             Log.i(TAG, prefix + "  LocaleList: " + localeList);
2456         }
2457         String[] mimeTypes = node.getReceiveContentMimeTypes();
2458         if (mimeTypes != null) {
2459             Log.i(TAG, prefix + "  MIME types: " + Arrays.toString(mimeTypes));
2460         }
2461         String hint = node.getHint();
2462         if (hint != null) {
2463             Log.i(TAG, prefix + "  Hint: " + hint);
2464             Log.i(TAG, prefix + "  Resource id: " + node.getHintIdEntry());
2465         }
2466         Bundle extras = node.getExtras();
2467         if (extras != null) {
2468             Log.i(TAG, prefix + "  Extras: " + extras);
2469         }
2470         if (node.isAssistBlocked()) {
2471             Log.i(TAG, prefix + "  BLOCKED");
2472         }
2473         AutofillId autofillId = node.getAutofillId();
2474         if (autofillId == null) {
2475             Log.i(TAG, prefix + " NO autofill ID");
2476         } else {
2477             Log.i(TAG, prefix + "  Autofill info: id= " + autofillId
2478                     + ", type=" + node.getAutofillType()
2479                     + ", options=" + Arrays.toString(node.getAutofillOptions())
2480                     + ", hints=" + Arrays.toString(node.getAutofillHints())
2481                     + ", value=" + node.getAutofillValue()
2482                     + ", sanitized=" + node.isSanitized()
2483                     + ", important=" + node.getImportantForAutofill());
2484         }
2485 
2486         final int NCHILDREN = node.getChildCount();
2487         if (NCHILDREN > 0) {
2488             Log.i(TAG, prefix + "  Children:");
2489             String cprefix = prefix + "    ";
2490             for (int i=0; i<NCHILDREN; i++) {
2491                 ViewNode cnode = node.getChildAt(i);
2492                 dump(cprefix, cnode, showSensitive);
2493             }
2494         }
2495     }
2496 
2497     /**
2498      * Sets the task id is associated with the activity from which this AssistStructure was
2499      * generated.
2500      * @hide
2501      */
setTaskId(int taskId)2502     public void setTaskId(int taskId) {
2503         mTaskId = taskId;
2504     }
2505 
2506     /**
2507      * @return The task id for the associated activity.
2508      *
2509      * @hide
2510      */
getTaskId()2511     public int getTaskId() {
2512         return mTaskId;
2513     }
2514 
2515     /**
2516      * Sets the activity that is associated with this AssistStructure.
2517      * @hide
2518      */
setActivityComponent(ComponentName componentName)2519     public void setActivityComponent(ComponentName componentName) {
2520         mActivityComponent = componentName;
2521     }
2522 
2523     /**
2524      * Return the activity this AssistStructure came from.
2525      */
getActivityComponent()2526     public ComponentName getActivityComponent() {
2527         return mActivityComponent;
2528     }
2529 
2530     /** @hide */
getFlags()2531     public int getFlags() {
2532         return mFlags;
2533     }
2534 
2535     /**
2536      * Returns whether the activity associated with this AssistStructure was the home activity
2537      * (Launcher) at the time the assist data was acquired.
2538      * @return Whether the activity was the home activity.
2539      * @see android.content.Intent#CATEGORY_HOME
2540      */
isHomeActivity()2541     public boolean isHomeActivity() {
2542         return mIsHomeActivity;
2543     }
2544 
2545     /**
2546      * Return the number of window contents that have been collected in this assist data.
2547      */
getWindowNodeCount()2548     public int getWindowNodeCount() {
2549         ensureData();
2550         return mWindowNodes.size();
2551     }
2552 
2553     /**
2554      * Return one of the windows in the assist data.
2555      * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1.
2556      */
getWindowNodeAt(int index)2557     public WindowNode getWindowNodeAt(int index) {
2558         ensureData();
2559         return mWindowNodes.get(index);
2560     }
2561 
2562     // TODO(b/35708678): temporary method that disable one-way warning flag on binder.
2563     /** @hide */
ensureDataForAutofill()2564     public void ensureDataForAutofill() {
2565         if (mHaveData) {
2566             return;
2567         }
2568         mHaveData = true;
2569         Binder.allowBlocking(mReceiveChannel);
2570         try {
2571             ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
2572             reader.go();
2573         } finally {
2574             Binder.defaultBlocking(mReceiveChannel);
2575         }
2576     }
2577 
2578     /** @hide */
ensureData()2579     public void ensureData() {
2580         if (mHaveData) {
2581             return;
2582         }
2583         mHaveData = true;
2584         ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
2585         reader.go();
2586     }
2587 
waitForReady()2588     boolean waitForReady() {
2589         boolean skipStructure = false;
2590         synchronized (this) {
2591             long endTime = SystemClock.uptimeMillis() + 5000;
2592             long now;
2593             while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) {
2594                 try {
2595                     wait(endTime-now);
2596                 } catch (InterruptedException e) {
2597                 }
2598             }
2599             if (mPendingAsyncChildren.size() > 0) {
2600                 // We waited too long, assume none of the assist structure is valid.
2601                 Log.w(TAG, "Skipping assist structure, waiting too long for async children (have "
2602                         + mPendingAsyncChildren.size() + " remaining");
2603                 skipStructure = true;
2604             }
2605         }
2606         return !skipStructure;
2607     }
2608 
2609     /** @hide */
clearSendChannel()2610     public void clearSendChannel() {
2611         if (mSendChannel != null) {
2612             mSendChannel.mAssistStructure = null;
2613         }
2614     }
2615 
2616     @Override
describeContents()2617     public int describeContents() {
2618         return 0;
2619     }
2620 
2621     @Override
writeToParcel(Parcel out, int flags)2622     public void writeToParcel(Parcel out, int flags) {
2623         out.writeInt(mTaskId);
2624         ComponentName.writeToParcel(mActivityComponent, out);
2625         out.writeInt(mIsHomeActivity ? 1 : 0);
2626         if (mHaveData) {
2627             // This object holds its data.  We want to write a send channel that the
2628             // other side can use to retrieve that data.
2629             if (mSendChannel == null) {
2630                 mSendChannel = new SendChannel(this);
2631             }
2632             out.writeStrongBinder(mSendChannel);
2633         } else {
2634             // This object doesn't hold its data, so just propagate along its receive channel.
2635             out.writeStrongBinder(mReceiveChannel);
2636         }
2637     }
2638 
2639     public static final @android.annotation.NonNull Parcelable.Creator<AssistStructure> CREATOR
2640             = new Parcelable.Creator<AssistStructure>() {
2641         @Override
2642         public AssistStructure createFromParcel(Parcel in) {
2643             return new AssistStructure(in);
2644         }
2645 
2646         @Override
2647         public AssistStructure[] newArray(int size) {
2648             return new AssistStructure[size];
2649         }
2650     };
2651 }
2652