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