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