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