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