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