blob: ed3a2967519e55ebab8ad91f54e9a4c651657740 [file] [log] [blame]
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07001package android.app.assist;
2
Felipe Lemef8a81742017-03-17 18:05:01 -07003import android.annotation.NonNull;
Philip P. Moltmann495cadd2017-03-10 16:45:02 -08004import android.annotation.Nullable;
Felipe Leme1dfa9a02018-10-17 17:24:37 -07005import android.annotation.SystemApi;
Felipe Leme19652c02019-02-04 13:01:29 -08006import android.annotation.TestApi;
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07007import android.app.Activity;
Dianne Hackborn16036f22015-06-22 14:05:51 -07008import android.content.ComponentName;
Svetoslav Ganov24c90452017-12-27 15:17:14 -08009import android.content.Context;
Dianne Hackborn70d8be72015-06-23 19:33:02 +000010import android.graphics.Matrix;
Dianne Hackborn16036f22015-06-22 14:05:51 -070011import android.graphics.Rect;
Felipe Leme4711ed92017-04-21 16:47:18 -070012import android.net.Uri;
Dianne Hackborn3e8125b2015-07-22 17:02:10 -070013import android.os.BadParcelableException;
Dianne Hackborn16036f22015-06-22 14:05:51 -070014import android.os.Binder;
15import android.os.Bundle;
16import android.os.IBinder;
Felipe Lemeb4ca7012017-03-22 18:30:07 -070017import android.os.LocaleList;
Dianne Hackborn69c6adc2015-06-02 10:52:59 -070018import android.os.Parcel;
19import android.os.Parcelable;
Dianne Hackborn16036f22015-06-22 14:05:51 -070020import android.os.PooledStringReader;
21import android.os.PooledStringWriter;
22import android.os.RemoteException;
23import android.os.SystemClock;
Felipe Leme73fedac2017-05-12 09:52:07 -070024import android.service.autofill.FillRequest;
Dianne Hackborn16036f22015-06-22 14:05:51 -070025import android.text.TextUtils;
26import android.util.Log;
Felipe Leme25bf7872017-03-28 15:32:29 -070027import android.util.Pair;
Dianne Hackborn16036f22015-06-22 14:05:51 -070028import android.view.View;
felipeal53308c12018-02-07 14:43:30 +010029import android.view.View.AutofillImportance;
Dianne Hackborn16036f22015-06-22 14:05:51 -070030import android.view.ViewRootImpl;
Felipe Lemec3241002017-02-15 12:55:11 -080031import android.view.ViewStructure;
Felipe Leme25bf7872017-03-28 15:32:29 -070032import android.view.ViewStructure.HtmlInfo;
33import android.view.ViewStructure.HtmlInfo.Builder;
Dianne Hackborn16036f22015-06-22 14:05:51 -070034import android.view.WindowManager;
35import android.view.WindowManagerGlobal;
Felipe Leme640f30a2017-03-06 15:44:06 -080036import android.view.autofill.AutofillId;
37import android.view.autofill.AutofillValue;
Dianne Hackborn16036f22015-06-22 14:05:51 -070038
Felipe Leme5dc45ca2018-01-03 09:02:27 -080039import com.android.internal.util.Preconditions;
40
Dianne Hackborn16036f22015-06-22 14:05:51 -070041import java.util.ArrayList;
Felipe Leme16aafc32017-02-27 13:41:37 -080042import java.util.Arrays;
Felipe Leme09a70622017-04-27 15:24:19 -070043import java.util.List;
Dianne Hackborn69c6adc2015-06-02 10:52:59 -070044
45/**
Laura Davis43e75d92018-08-10 15:46:06 -070046 * <p>This API automatically creates assist data from the platform's
47 * implementation of assist and autofill.
Felipe Leme30e9b262017-04-21 11:29:30 -070048 *
Felipe Leme2f6fc722017-05-31 11:57:46 -070049 * <p>The structure is used for assist purposes when created by
Felipe Leme30e9b262017-04-21 11:29:30 -070050 * {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)},
51 * or {@link View#onProvideVirtualStructure(ViewStructure)}.
52 *
Laura Davis43e75d92018-08-10 15:46:06 -070053 * <p>The structure is also used for autofill purposes when created by
Felipe Leme30e9b262017-04-21 11:29:30 -070054 * {@link View#onProvideAutofillStructure(ViewStructure, int)},
55 * or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}.
56 *
Laura Davis43e75d92018-08-10 15:46:06 -070057 * <p>For performance reasons, some properties of the assist data might only be available for
58 * assist or autofill purposes. In those cases, a property's availability will be documented
59 * in its javadoc.
60 *
61 * <p>To learn about using Autofill in your app, read the
62 * <a href="/guide/topics/text/autofill">Autofill Framework</a> guides.
Dianne Hackborn69c6adc2015-06-02 10:52:59 -070063 */
Dianne Hackborn16036f22015-06-22 14:05:51 -070064public class AssistStructure implements Parcelable {
Winson Chung48b25652018-10-22 14:04:30 -070065 private static final String TAG = "AssistStructure";
Dianne Hackborn69c6adc2015-06-02 10:52:59 -070066
Winson Chung48b25652018-10-22 14:04:30 -070067 private static final boolean DEBUG_PARCEL = false;
68 private static final boolean DEBUG_PARCEL_CHILDREN = false;
69 private static final boolean DEBUG_PARCEL_TREE = false;
Dianne Hackborn782d4982015-07-08 17:36:37 -070070
Winson Chung48b25652018-10-22 14:04:30 -070071 private static final int VALIDATE_WINDOW_TOKEN = 0x11111111;
72 private static final int VALIDATE_VIEW_TOKEN = 0x22222222;
Dianne Hackborn3e8125b2015-07-22 17:02:10 -070073
Winson Chung48b25652018-10-22 14:04:30 -070074 private boolean mHaveData;
Dianne Hackborn16036f22015-06-22 14:05:51 -070075
Winson Chung48b25652018-10-22 14:04:30 -070076 // The task id and component of the activity which this assist structure is for
77 private int mTaskId;
78 private ComponentName mActivityComponent;
Amith Yamasani858f98d2017-02-22 12:59:53 -080079 private boolean mIsHomeActivity;
Felipe Leme0aa4c502017-04-26 12:36:01 -070080 private int mFlags;
Adam Hedf596842018-10-04 15:59:57 -070081 private int mAutofillFlags;
Dianne Hackborn16036f22015-06-22 14:05:51 -070082
Winson Chung48b25652018-10-22 14:04:30 -070083 private final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
Dianne Hackborn16036f22015-06-22 14:05:51 -070084
Winson Chung48b25652018-10-22 14:04:30 -070085 private final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
Dianne Hackborn16036f22015-06-22 14:05:51 -070086
Winson Chung48b25652018-10-22 14:04:30 -070087 private SendChannel mSendChannel;
88 private IBinder mReceiveChannel;
Dianne Hackborn16036f22015-06-22 14:05:51 -070089
Winson Chung48b25652018-10-22 14:04:30 -070090 private Rect mTmpRect = new Rect();
Dianne Hackborn16036f22015-06-22 14:05:51 -070091
Winson Chung48b25652018-10-22 14:04:30 -070092 private boolean mSanitizeOnWrite = false;
Amith Yamasani858f98d2017-02-22 12:59:53 -080093 private long mAcquisitionStartTime;
94 private long mAcquisitionEndTime;
Felipe Leme0200d9e2017-01-24 15:10:26 -080095
Winson Chung48b25652018-10-22 14:04:30 -070096 private static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
97 private static final String DESCRIPTOR = "android.app.AssistStructure";
Dianne Hackborn16036f22015-06-22 14:05:51 -070098
Amith Yamasani858f98d2017-02-22 12:59:53 -080099 /** @hide */
100 public void setAcquisitionStartTime(long acquisitionStartTime) {
101 mAcquisitionStartTime = acquisitionStartTime;
102 }
103
104 /** @hide */
105 public void setAcquisitionEndTime(long acquisitionEndTime) {
106 mAcquisitionEndTime = acquisitionEndTime;
107 }
108
109 /**
110 * @hide
111 * Set the home activity flag.
112 */
113 public void setHomeActivity(boolean isHomeActivity) {
114 mIsHomeActivity = isHomeActivity;
115 }
116
117 /**
118 * Returns the time when the activity started generating assist data to build the
119 * AssistStructure. The time is as specified by {@link SystemClock#uptimeMillis()}.
120 *
121 * @see #getAcquisitionEndTime()
122 * @return Returns the acquisition start time of the assist data, in milliseconds.
123 */
124 public long getAcquisitionStartTime() {
125 ensureData();
126 return mAcquisitionStartTime;
127 }
128
129 /**
130 * Returns the time when the activity finished generating assist data to build the
131 * AssistStructure. The time is as specified by {@link SystemClock#uptimeMillis()}.
132 *
133 * @see #getAcquisitionStartTime()
134 * @return Returns the acquisition end time of the assist data, in milliseconds.
135 */
136 public long getAcquisitionEndTime() {
137 ensureData();
138 return mAcquisitionEndTime;
139 }
140
Dianne Hackborn782d4982015-07-08 17:36:37 -0700141 final static class SendChannel extends Binder {
142 volatile AssistStructure mAssistStructure;
143
144 SendChannel(AssistStructure as) {
145 mAssistStructure = as;
146 }
147
Dianne Hackborn16036f22015-06-22 14:05:51 -0700148 @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
149 throws RemoteException {
150 if (code == TRANSACTION_XFER) {
Dianne Hackborn782d4982015-07-08 17:36:37 -0700151 AssistStructure as = mAssistStructure;
152 if (as == null) {
153 return true;
154 }
155
Dianne Hackborn16036f22015-06-22 14:05:51 -0700156 data.enforceInterface(DESCRIPTOR);
Dianne Hackborn782d4982015-07-08 17:36:37 -0700157 IBinder token = data.readStrongBinder();
158 if (DEBUG_PARCEL) Log.d(TAG, "Request for data on " + as
159 + " using token " + token);
160 if (token != null) {
161 if (DEBUG_PARCEL) Log.d(TAG, "Resuming partial write of " + token);
162 if (token instanceof ParcelTransferWriter) {
163 ParcelTransferWriter xfer = (ParcelTransferWriter)token;
164 xfer.writeToParcel(as, reply);
165 return true;
166 }
167 Log.w(TAG, "Caller supplied bad token type: " + token);
168 // Don't write anything; this is the end of the data.
169 return true;
170 }
171 //long start = SystemClock.uptimeMillis();
172 ParcelTransferWriter xfer = new ParcelTransferWriter(as, reply);
173 xfer.writeToParcel(as, reply);
174 //Log.i(TAG, "Time to parcel: " + (SystemClock.uptimeMillis()-start) + "ms");
Dianne Hackborn16036f22015-06-22 14:05:51 -0700175 return true;
176 } else {
177 return super.onTransact(code, data, reply, flags);
178 }
179 }
180 }
181
Dianne Hackborn782d4982015-07-08 17:36:37 -0700182 final static class ViewStackEntry {
183 ViewNode node;
184 int curChild;
185 int numChildren;
186 }
187
188 final static class ParcelTransferWriter extends Binder {
189 final boolean mWriteStructure;
190 int mCurWindow;
191 int mNumWindows;
192 final ArrayList<ViewStackEntry> mViewStack = new ArrayList<>();
193 ViewStackEntry mCurViewStackEntry;
194 int mCurViewStackPos;
195 int mNumWrittenWindows;
196 int mNumWrittenViews;
197 final float[] mTmpMatrix = new float[9];
Felipe Leme0200d9e2017-01-24 15:10:26 -0800198 final boolean mSanitizeOnWrite;
Dianne Hackborn782d4982015-07-08 17:36:37 -0700199
200 ParcelTransferWriter(AssistStructure as, Parcel out) {
Felipe Leme0200d9e2017-01-24 15:10:26 -0800201 mSanitizeOnWrite = as.mSanitizeOnWrite;
Dianne Hackborn782d4982015-07-08 17:36:37 -0700202 mWriteStructure = as.waitForReady();
Felipe Leme0aa4c502017-04-26 12:36:01 -0700203 out.writeInt(as.mFlags);
Adam Hedf596842018-10-04 15:59:57 -0700204 out.writeInt(as.mAutofillFlags);
Amith Yamasani858f98d2017-02-22 12:59:53 -0800205 out.writeLong(as.mAcquisitionStartTime);
206 out.writeLong(as.mAcquisitionEndTime);
Dianne Hackborn782d4982015-07-08 17:36:37 -0700207 mNumWindows = as.mWindowNodes.size();
208 if (mWriteStructure && mNumWindows > 0) {
209 out.writeInt(mNumWindows);
210 } else {
211 out.writeInt(0);
212 }
213 }
214
215 void writeToParcel(AssistStructure as, Parcel out) {
216 int start = out.dataPosition();
217 mNumWrittenWindows = 0;
218 mNumWrittenViews = 0;
219 boolean more = writeToParcelInner(as, out);
220 Log.i(TAG, "Flattened " + (more ? "partial" : "final") + " assist data: "
221 + (out.dataPosition() - start)
222 + " bytes, containing " + mNumWrittenWindows + " windows, "
223 + mNumWrittenViews + " views");
224 }
225
226 boolean writeToParcelInner(AssistStructure as, Parcel out) {
227 if (mNumWindows == 0) {
228 return false;
229 }
230 if (DEBUG_PARCEL) Log.d(TAG, "Creating PooledStringWriter @ " + out.dataPosition());
231 PooledStringWriter pwriter = new PooledStringWriter(out);
232 while (writeNextEntryToParcel(as, out, pwriter)) {
Dianne Hackborn86cbc2b2015-07-28 18:07:13 -0700233 // If the parcel is above the IPC limit, then we are getting too
Dianne Hackborn782d4982015-07-08 17:36:37 -0700234 // large for a single IPC so stop here and let the caller come back when it
235 // is ready for more.
Dianne Hackborn86cbc2b2015-07-28 18:07:13 -0700236 if (out.dataSize() > IBinder.MAX_IPC_SIZE) {
Dianne Hackborn782d4982015-07-08 17:36:37 -0700237 if (DEBUG_PARCEL) Log.d(TAG, "Assist data size is " + out.dataSize()
238 + " @ pos " + out.dataPosition() + "; returning partial result");
239 out.writeInt(0);
240 out.writeStrongBinder(this);
241 if (DEBUG_PARCEL) Log.d(TAG, "Finishing PooledStringWriter @ "
242 + out.dataPosition() + ", size " + pwriter.getStringCount());
243 pwriter.finish();
244 return true;
245 }
246 }
247 if (DEBUG_PARCEL) Log.d(TAG, "Finishing PooledStringWriter @ "
248 + out.dataPosition() + ", size " + pwriter.getStringCount());
249 pwriter.finish();
250 mViewStack.clear();
251 return false;
252 }
253
254 void pushViewStackEntry(ViewNode node, int pos) {
255 ViewStackEntry entry;
256 if (pos >= mViewStack.size()) {
257 entry = new ViewStackEntry();
258 mViewStack.add(entry);
259 if (DEBUG_PARCEL_TREE) Log.d(TAG, "New stack entry at " + pos + ": " + entry);
260 } else {
261 entry = mViewStack.get(pos);
262 if (DEBUG_PARCEL_TREE) Log.d(TAG, "Existing stack entry at " + pos + ": " + entry);
263 }
264 entry.node = node;
265 entry.numChildren = node.getChildCount();
266 entry.curChild = 0;
267 mCurViewStackEntry = entry;
268 }
269
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700270 void writeView(ViewNode child, Parcel out, PooledStringWriter pwriter, int levelAdj) {
271 if (DEBUG_PARCEL) Log.d(TAG, "write view: at " + out.dataPosition()
272 + ", windows=" + mNumWrittenWindows
273 + ", views=" + mNumWrittenViews
274 + ", level=" + (mCurViewStackPos+levelAdj));
275 out.writeInt(VALIDATE_VIEW_TOKEN);
Felipe Leme0200d9e2017-01-24 15:10:26 -0800276 int flags = child.writeSelfToParcel(out, pwriter, mSanitizeOnWrite, mTmpMatrix);
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700277 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
Dianne Hackborn782d4982015-07-08 17:36:37 -0700290 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++;
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700299 writeView(child, out, pwriter, 1);
Dianne Hackborn782d4982015-07-08 17:36:37 -0700300 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);
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700327 out.writeInt(VALIDATE_WINDOW_TOKEN);
Dianne Hackborn782d4982015-07-08 17:36:37 -0700328 win.writeSelfToParcel(out, pwriter, mTmpMatrix);
329 mNumWrittenWindows++;
330 ViewNode root = win.mRoot;
331 mCurViewStackPos = 0;
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700332 if (DEBUG_PARCEL_TREE) Log.d(TAG, "Writing initial root view " + root);
333 writeView(root, out, pwriter, 0);
Dianne Hackborn782d4982015-07-08 17:36:37 -0700334 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
352 ParcelTransferReader(IBinder channel) {
353 mChannel = channel;
354 }
355
356 void go() {
357 fetchData();
Felipe Leme0aa4c502017-04-26 12:36:01 -0700358 mFlags = mCurParcel.readInt();
Adam Hedf596842018-10-04 15:59:57 -0700359 mAutofillFlags = mCurParcel.readInt();
Amith Yamasani858f98d2017-02-22 12:59:53 -0800360 mAcquisitionStartTime = mCurParcel.readLong();
361 mAcquisitionEndTime = mCurParcel.readLong();
Dianne Hackborn782d4982015-07-08 17:36:37 -0700362 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);
Felipe Lemec52b6ea2017-11-17 08:42:00 -0800376 mCurParcel.recycle();
377 mCurParcel = null; // Parcel cannot be used after recycled.
Dianne Hackborn782d4982015-07-08 17:36:37 -0700378 }
379
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700380 Parcel readParcel(int validateToken, int level) {
Dianne Hackborn782d4982015-07-08 17:36:37 -0700381 if (DEBUG_PARCEL) Log.d(TAG, "readParcel: at " + mCurParcel.dataPosition()
382 + ", avail=" + mCurParcel.dataAvail() + ", windows=" + mNumReadWindows
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700383 + ", 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 }
Dianne Hackborn782d4982015-07-08 17:36:37 -0700390 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
413 private void fetchData() {
414 Parcel data = Parcel.obtain();
Dianne Hackborn782d4982015-07-08 17:36:37 -0700415 try {
Felipe Lemec52b6ea2017-11-17 08:42:00 -0800416 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();
Dianne Hackborn782d4982015-07-08 17:36:37 -0700431 }
Dianne Hackborn782d4982015-07-08 17:36:37 -0700432 mNumReadWindows = mNumReadViews = 0;
433 }
434 }
435
Dianne Hackborn16036f22015-06-22 14:05:51 -0700436 final static class ViewNodeText {
437 CharSequence mText;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700438 float mTextSize;
439 int mTextStyle;
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -0700440 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;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700446 String mHint;
447
448 ViewNodeText() {
449 }
450
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -0700451 boolean isSimple() {
452 return mTextBackgroundColor == ViewNode.TEXT_COLOR_UNDEFINED
453 && mTextSelectionStart == 0 && mTextSelectionEnd == 0
454 && mLineCharOffsets == null && mLineBaselines == null && mHint == null;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700455 }
456
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -0700457 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
Felipe Leme0200d9e2017-01-24 15:10:26 -0800472 void writeToParcel(Parcel out, boolean simple, boolean writeSensitive) {
473 TextUtils.writeToParcel(writeSensitive ? mText : "", out, 0);
Dianne Hackborn16036f22015-06-22 14:05:51 -0700474 out.writeFloat(mTextSize);
475 out.writeInt(mTextStyle);
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -0700476 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 }
Dianne Hackborn16036f22015-06-22 14:05:51 -0700485 }
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
Svet Ganovfd31f852017-04-26 15:54:27 -0700500 WindowNode(AssistStructure assist, ViewRootImpl root, boolean forAutoFill, int flags) {
Dianne Hackborn16036f22015-06-22 14:05:51 -0700501 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();
Felipe Leme6d553872016-12-08 17:13:25 -0800511
Felipe Leme33791fd2017-02-16 08:07:56 -0800512 ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
Felipe Leme71377a42017-02-14 18:16:11 -0800513 if ((root.getWindowFlags() & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
Felipe Leme6d553872016-12-08 17:13:25 -0800514 if (forAutoFill) {
Svetoslav Ganov24c90452017-12-27 15:17:14 -0800515 final int viewFlags = resolveViewAutofillFlags(view.getContext(), flags);
516 view.onProvideAutofillStructure(builder, viewFlags);
Felipe Leme1ca634a2016-11-28 17:21:21 -0800517 } else {
Felipe Leme71377a42017-02-14 18:16:11 -0800518 // 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
Felipe Leme6d553872016-12-08 17:13:25 -0800520 view.onProvideStructure(builder);
Felipe Leme71377a42017-02-14 18:16:11 -0800521 builder.setAssistBlocked(true);
522 return;
Felipe Leme1ca634a2016-11-28 17:21:21 -0800523 }
Dianne Hackborn16036f22015-06-22 14:05:51 -0700524 }
Felipe Leme6d553872016-12-08 17:13:25 -0800525 if (forAutoFill) {
Svetoslav Ganov24c90452017-12-27 15:17:14 -0800526 final int viewFlags = resolveViewAutofillFlags(view.getContext(), flags);
527 view.dispatchProvideAutofillStructure(builder, viewFlags);
Felipe Leme1ca634a2016-11-28 17:21:21 -0800528 } else {
Felipe Leme6d553872016-12-08 17:13:25 -0800529 view.dispatchProvideStructure(builder);
Felipe Leme1ca634a2016-11-28 17:21:21 -0800530 }
Dianne Hackborn16036f22015-06-22 14:05:51 -0700531 }
532
Dianne Hackborn782d4982015-07-08 17:36:37 -0700533 WindowNode(ParcelTransferReader reader) {
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700534 Parcel in = reader.readParcel(VALIDATE_WINDOW_TOKEN, 0);
Dianne Hackborn782d4982015-07-08 17:36:37 -0700535 reader.mNumReadWindows++;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700536 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();
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700542 mRoot = new ViewNode(reader, 0);
Dianne Hackborn16036f22015-06-22 14:05:51 -0700543 }
544
Svetoslav Ganov24c90452017-12-27 15:17:14 -0800545 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
Dianne Hackborn782d4982015-07-08 17:36:37 -0700551 void writeSelfToParcel(Parcel out, PooledStringWriter pwriter, float[] tmpMatrix) {
Dianne Hackborn16036f22015-06-22 14:05:51 -0700552 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);
Dianne Hackborn16036f22015-06-22 14:05:51 -0700558 }
559
560 /**
561 * Returns the left edge of the window, in pixels, relative to the left
562 * edge of the screen.
563 */
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 */
572 public int getTop() {
573 return mY;
574 }
575
576 /**
577 * Returns the total width of the window in pixels.
578 */
579 public int getWidth() {
580 return mWidth;
581 }
582
583 /**
584 * Returns the total height of the window in pixels.
585 */
586 public int getHeight() {
587 return mHeight;
588 }
589
590 /**
591 * Returns the title associated with the window, if it has one.
592 */
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 */
601 public int getDisplayId() {
602 return mDisplayId;
603 }
604
605 /**
606 * Returns the {@link ViewNode} containing the root content of the window.
607 */
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
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000628 int mId = View.NO_ID;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700629 String mIdPackage;
630 String mIdType;
631 String mIdEntry;
Felipe Leme16aafc32017-02-27 13:41:37 -0800632
Felipe Leme640f30a2017-03-06 15:44:06 -0800633 AutofillId mAutofillId;
Felipe Leme30e9b262017-04-21 11:29:30 -0700634 @View.AutofillType int mAutofillType = View.AUTOFILL_TYPE_NONE;
Philip P. Moltmann81192b42017-03-29 13:58:59 -0700635 @Nullable String[] mAutofillHints;
Felipe Leme640f30a2017-03-06 15:44:06 -0800636 AutofillValue mAutofillValue;
Felipe Leme7e4c2052017-04-18 09:45:58 -0700637 CharSequence[] mAutofillOptions;
Felipe Leme0200d9e2017-01-24 15:10:26 -0800638 boolean mSanitized;
Felipe Leme25bf7872017-03-28 15:32:29 -0700639 HtmlInfo mHtmlInfo;
Felipe Lemeaa7e2292017-10-05 18:19:48 -0700640 int mMinEms = -1;
641 int mMaxEms = -1;
642 int mMaxLength = -1;
Felipe Leme5dc45ca2018-01-03 09:02:27 -0800643 @Nullable String mTextIdEntry;
felipeal53308c12018-02-07 14:43:30 +0100644 @AutofillImportance int mImportantForAutofill;
Felipe Leme16aafc32017-02-27 13:41:37 -0800645
Felipe Lemecde040a2017-03-31 17:26:34 -0700646 // POJO used to override some autofill-related values when the node is parcelized.
647 // Not written to parcel.
648 AutofillOverlay mAutofillOverlay;
649
Dianne Hackborn16036f22015-06-22 14:05:51 -0700650 int mX;
651 int mY;
652 int mScrollX;
653 int mScrollY;
654 int mWidth;
655 int mHeight;
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000656 Matrix mMatrix;
657 float mElevation;
658 float mAlpha = 1.0f;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700659
660 static final int FLAGS_DISABLED = 0x00000001;
661 static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
662 static final int FLAGS_FOCUSABLE = 0x00000010;
663 static final int FLAGS_FOCUSED = 0x00000020;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700664 static final int FLAGS_SELECTED = 0x00000040;
665 static final int FLAGS_ASSIST_BLOCKED = 0x00000080;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700666 static final int FLAGS_CHECKABLE = 0x00000100;
667 static final int FLAGS_CHECKED = 0x00000200;
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000668 static final int FLAGS_CLICKABLE = 0x00000400;
669 static final int FLAGS_LONG_CLICKABLE = 0x00000800;
670 static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x00001000;
671 static final int FLAGS_ACTIVATED = 0x00002000;
672 static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000;
Amith Yamasani858f98d2017-02-22 12:59:53 -0800673 static final int FLAGS_OPAQUE = 0x00008000;
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000674
675 static final int FLAGS_HAS_MATRIX = 0x40000000;
676 static final int FLAGS_HAS_ALPHA = 0x20000000;
677 static final int FLAGS_HAS_ELEVATION = 0x10000000;
678 static final int FLAGS_HAS_SCROLL = 0x08000000;
679 static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
680 static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
681 static final int FLAGS_HAS_TEXT = 0x01000000;
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -0700682 static final int FLAGS_HAS_COMPLEX_TEXT = 0x00800000;
683 static final int FLAGS_HAS_EXTRAS = 0x00400000;
684 static final int FLAGS_HAS_ID = 0x00200000;
685 static final int FLAGS_HAS_CHILDREN = 0x00100000;
Felipe Lemec3241002017-02-15 12:55:11 -0800686 static final int FLAGS_HAS_URL = 0x00080000;
Felipe Leme16aafc32017-02-27 13:41:37 -0800687 static final int FLAGS_HAS_INPUT_TYPE = 0x00040000;
Felipe Lemeb4ca7012017-03-22 18:30:07 -0700688 static final int FLAGS_HAS_LOCALE_LIST = 0x00010000;
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000689 static final int FLAGS_ALL_CONTROL = 0xfff00000;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700690
Adam Hedf596842018-10-04 15:59:57 -0700691 static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID = 0x001;
692 static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID = 0x002;
693 static final int AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE = 0x004;
694 static final int AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE = 0x008;
695 static final int AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS = 0x010;
696 static final int AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS = 0x020;
697 static final int AUTOFILL_FLAGS_HAS_HTML_INFO = 0x040;
698 static final int AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY = 0x080;
699 static final int AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS = 0x100;
700 static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS = 0x200;
701 static final int AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH = 0x400;
702
Dianne Hackborn16036f22015-06-22 14:05:51 -0700703 int mFlags;
Adam Hedf596842018-10-04 15:59:57 -0700704 int mAutofillFlags;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700705
706 String mClassName;
707 CharSequence mContentDescription;
708
709 ViewNodeText mText;
Felipe Leme16aafc32017-02-27 13:41:37 -0800710 int mInputType;
Felipe Leme114a4412017-09-26 13:02:11 -0700711 String mWebScheme;
Felipe Leme4711ed92017-04-21 16:47:18 -0700712 String mWebDomain;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700713 Bundle mExtras;
Felipe Lemeb4ca7012017-03-22 18:30:07 -0700714 LocaleList mLocaleList;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700715
716 ViewNode[] mChildren;
717
Felipe Leme1dfa9a02018-10-17 17:24:37 -0700718 // TODO(b/111276913): temporarily made public / @hide until we decide what will be used by
Felipe Leme19652c02019-02-04 13:01:29 -0800719 // COntent Capture.
Felipe Leme1dfa9a02018-10-17 17:24:37 -0700720 /** @hide */
721 @SystemApi
Felipe Leme19652c02019-02-04 13:01:29 -0800722 @TestApi
Felipe Leme1dfa9a02018-10-17 17:24:37 -0700723 public ViewNode() {
Dianne Hackborn16036f22015-06-22 14:05:51 -0700724 }
725
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700726 ViewNode(ParcelTransferReader reader, int nestingLevel) {
727 final Parcel in = reader.readParcel(VALIDATE_VIEW_TOKEN, nestingLevel);
Dianne Hackborn782d4982015-07-08 17:36:37 -0700728 reader.mNumReadViews++;
729 final PooledStringReader preader = reader.mStringReader;
Dianne Hackborn16036f22015-06-22 14:05:51 -0700730 mClassName = preader.readString();
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000731 mFlags = in.readInt();
732 final int flags = mFlags;
Adam Hedf596842018-10-04 15:59:57 -0700733 mAutofillFlags = in.readInt();
734 final int autofillFlags = mAutofillFlags;
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000735 if ((flags&FLAGS_HAS_ID) != 0) {
736 mId = in.readInt();
Felipe Leme5dc45ca2018-01-03 09:02:27 -0800737 if (mId != View.NO_ID) {
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000738 mIdEntry = preader.readString();
739 if (mIdEntry != null) {
740 mIdType = preader.readString();
741 mIdPackage = preader.readString();
742 }
743 }
Dianne Hackborn16036f22015-06-22 14:05:51 -0700744 }
Felipe Leme1a1e4682017-03-13 16:34:03 -0700745
Adam Hedf596842018-10-04 15:59:57 -0700746 if (autofillFlags != 0) {
Felipe Leme0200d9e2017-01-24 15:10:26 -0800747 mSanitized = in.readInt() == 1;
felipeal53308c12018-02-07 14:43:30 +0100748 mImportantForAutofill = in.readInt();
Adam Hedf596842018-10-04 15:59:57 -0700749
750 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID) != 0) {
751 int autofillViewId = in.readInt();
752 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID) != 0) {
753 mAutofillId = new AutofillId(autofillViewId, in.readInt());
754 } else {
755 mAutofillId = new AutofillId(autofillViewId);
756 }
757 }
758 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
759 mAutofillType = in.readInt();
760 }
761 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS) != 0) {
762 mAutofillHints = in.readStringArray();
763 }
764 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE) != 0) {
765 mAutofillValue = in.readParcelable(null);
766 }
767 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
768 mAutofillOptions = in.readCharSequenceArray();
769 }
770 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HTML_INFO) != 0) {
771 mHtmlInfo = in.readParcelable(null);
772 }
773 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS) != 0) {
774 mMinEms = in.readInt();
775 }
776 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS) != 0) {
777 mMaxEms = in.readInt();
778 }
779 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
780 mMaxLength = in.readInt();
781 }
782 if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
783 mTextIdEntry = preader.readString();
784 }
Felipe Leme29a5b0d2016-10-25 14:57:11 -0700785 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000786 if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
787 mX = in.readInt();
788 mY = in.readInt();
789 mWidth = in.readInt();
790 mHeight = in.readInt();
791 } else {
792 int val = in.readInt();
793 mX = val&0x7fff;
794 mY = (val>>16)&0x7fff;
795 val = in.readInt();
796 mWidth = val&0x7fff;
797 mHeight = (val>>16)&0x7fff;
798 }
799 if ((flags&FLAGS_HAS_SCROLL) != 0) {
800 mScrollX = in.readInt();
801 mScrollY = in.readInt();
802 }
803 if ((flags&FLAGS_HAS_MATRIX) != 0) {
804 mMatrix = new Matrix();
Dianne Hackborn782d4982015-07-08 17:36:37 -0700805 in.readFloatArray(reader.mTmpMatrix);
806 mMatrix.setValues(reader.mTmpMatrix);
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000807 }
808 if ((flags&FLAGS_HAS_ELEVATION) != 0) {
809 mElevation = in.readFloat();
810 }
811 if ((flags&FLAGS_HAS_ALPHA) != 0) {
812 mAlpha = in.readFloat();
813 }
814 if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
815 mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
816 }
817 if ((flags&FLAGS_HAS_TEXT) != 0) {
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -0700818 mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000819 }
Felipe Leme16aafc32017-02-27 13:41:37 -0800820 if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
821 mInputType = in.readInt();
822 }
Felipe Lemec3241002017-02-15 12:55:11 -0800823 if ((flags&FLAGS_HAS_URL) != 0) {
Felipe Leme114a4412017-09-26 13:02:11 -0700824 mWebScheme = in.readString();
Felipe Leme4711ed92017-04-21 16:47:18 -0700825 mWebDomain = in.readString();
Felipe Lemec3241002017-02-15 12:55:11 -0800826 }
Felipe Lemeb4ca7012017-03-22 18:30:07 -0700827 if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) {
828 mLocaleList = in.readParcelable(null);
829 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000830 if ((flags&FLAGS_HAS_EXTRAS) != 0) {
831 mExtras = in.readBundle();
832 }
833 if ((flags&FLAGS_HAS_CHILDREN) != 0) {
834 final int NCHILDREN = in.readInt();
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700835 if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) Log.d(TAG,
836 "Preparing to read " + NCHILDREN
837 + " children: @ #" + reader.mNumReadViews
838 + ", level " + nestingLevel);
Dianne Hackborn16036f22015-06-22 14:05:51 -0700839 mChildren = new ViewNode[NCHILDREN];
840 for (int i=0; i<NCHILDREN; i++) {
Dianne Hackborn3e8125b2015-07-22 17:02:10 -0700841 mChildren[i] = new ViewNode(reader, nestingLevel + 1);
Dianne Hackborn16036f22015-06-22 14:05:51 -0700842 }
Dianne Hackborn16036f22015-06-22 14:05:51 -0700843 }
844 }
845
Felipe Leme0200d9e2017-01-24 15:10:26 -0800846 int writeSelfToParcel(Parcel out, PooledStringWriter pwriter, boolean sanitizeOnWrite,
847 float[] tmpMatrix) {
Felipe Leme640f30a2017-03-06 15:44:06 -0800848 // Guard used to skip non-sanitized data when writing for autofill.
Felipe Leme0200d9e2017-01-24 15:10:26 -0800849 boolean writeSensitive = true;
850
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000851 int flags = mFlags & ~FLAGS_ALL_CONTROL;
Adam Hedf596842018-10-04 15:59:57 -0700852 int autofillFlags = 0;
Felipe Lemecde040a2017-03-31 17:26:34 -0700853
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000854 if (mId != View.NO_ID) {
855 flags |= FLAGS_HAS_ID;
856 }
857 if ((mX&~0x7fff) != 0 || (mY&~0x7fff) != 0
858 || (mWidth&~0x7fff) != 0 | (mHeight&~0x7fff) != 0) {
859 flags |= FLAGS_HAS_LARGE_COORDS;
860 }
861 if (mScrollX != 0 || mScrollY != 0) {
862 flags |= FLAGS_HAS_SCROLL;
863 }
864 if (mMatrix != null) {
865 flags |= FLAGS_HAS_MATRIX;
866 }
867 if (mElevation != 0) {
868 flags |= FLAGS_HAS_ELEVATION;
869 }
870 if (mAlpha != 1.0f) {
871 flags |= FLAGS_HAS_ALPHA;
872 }
873 if (mContentDescription != null) {
874 flags |= FLAGS_HAS_CONTENT_DESCRIPTION;
875 }
876 if (mText != null) {
877 flags |= FLAGS_HAS_TEXT;
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -0700878 if (!mText.isSimple()) {
879 flags |= FLAGS_HAS_COMPLEX_TEXT;
880 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000881 }
Felipe Leme16aafc32017-02-27 13:41:37 -0800882 if (mInputType != 0) {
883 flags |= FLAGS_HAS_INPUT_TYPE;
884 }
Felipe Leme114a4412017-09-26 13:02:11 -0700885 if (mWebScheme != null || mWebDomain != null) {
Felipe Lemec3241002017-02-15 12:55:11 -0800886 flags |= FLAGS_HAS_URL;
887 }
Felipe Lemeb4ca7012017-03-22 18:30:07 -0700888 if (mLocaleList != null) {
889 flags |= FLAGS_HAS_LOCALE_LIST;
890 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000891 if (mExtras != null) {
892 flags |= FLAGS_HAS_EXTRAS;
893 }
894 if (mChildren != null) {
895 flags |= FLAGS_HAS_CHILDREN;
896 }
Adam Hedf596842018-10-04 15:59:57 -0700897 if (mAutofillId != null) {
898 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID;
Felipe Lemea75333c2019-01-22 15:45:32 -0800899 if (mAutofillId.isVirtualInt()) {
Adam Hedf596842018-10-04 15:59:57 -0700900 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID;
901 }
902 }
903 if (mAutofillValue != null) {
904 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE;
905 }
906 if (mAutofillType != View.AUTOFILL_TYPE_NONE) {
907 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE;
908 }
909 if (mAutofillHints != null) {
910 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS;
911 }
912 if (mAutofillOptions != null) {
913 autofillFlags |= AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS;
914 }
915 if (mHtmlInfo instanceof Parcelable) {
916 autofillFlags |= AUTOFILL_FLAGS_HAS_HTML_INFO;
917 }
918 if (mMinEms > -1) {
919 autofillFlags |= AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS;
920 }
921 if (mMaxEms > -1) {
922 autofillFlags |= AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS;
923 }
924 if (mMaxLength > -1) {
925 autofillFlags |= AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH;
926 }
927 if (mTextIdEntry != null) {
928 autofillFlags |= AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY;
929 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000930
931 pwriter.writeString(mClassName);
Felipe Lemec01a8732017-02-22 17:26:06 -0800932
933 int writtenFlags = flags;
Adam Hedf596842018-10-04 15:59:57 -0700934 if (autofillFlags != 0 && (mSanitized || !sanitizeOnWrite)) {
Felipe Leme640f30a2017-03-06 15:44:06 -0800935 // Remove 'checked' from sanitized autofill request.
Felipe Lemec01a8732017-02-22 17:26:06 -0800936 writtenFlags = flags & ~FLAGS_CHECKED;
937 }
Felipe Lemecde040a2017-03-31 17:26:34 -0700938 if (mAutofillOverlay != null) {
939 if (mAutofillOverlay.focused) {
940 writtenFlags |= ViewNode.FLAGS_FOCUSED;
941 } else {
942 writtenFlags &= ~ViewNode.FLAGS_FOCUSED;
943 }
944 }
Felipe Lemec01a8732017-02-22 17:26:06 -0800945
946 out.writeInt(writtenFlags);
Adam Hedf596842018-10-04 15:59:57 -0700947 out.writeInt(autofillFlags);
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000948 if ((flags&FLAGS_HAS_ID) != 0) {
949 out.writeInt(mId);
Felipe Leme5dc45ca2018-01-03 09:02:27 -0800950 if (mId != View.NO_ID) {
Dianne Hackborn70d8be72015-06-23 19:33:02 +0000951 pwriter.writeString(mIdEntry);
952 if (mIdEntry != null) {
953 pwriter.writeString(mIdType);
954 pwriter.writeString(mIdPackage);
955 }
Dianne Hackborn16036f22015-06-22 14:05:51 -0700956 }
957 }
Felipe Leme1a1e4682017-03-13 16:34:03 -0700958
Adam Hedf596842018-10-04 15:59:57 -0700959 if (autofillFlags != 0) {
Felipe Leme0200d9e2017-01-24 15:10:26 -0800960 out.writeInt(mSanitized ? 1 : 0);
felipeal53308c12018-02-07 14:43:30 +0100961 out.writeInt(mImportantForAutofill);
Adam Hedf596842018-10-04 15:59:57 -0700962 writeSensitive = mSanitized || !sanitizeOnWrite;
963 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIEW_ID) != 0) {
964 out.writeInt(mAutofillId.getViewId());
965 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VIRTUAL_VIEW_ID) != 0) {
Felipe Lemea75333c2019-01-22 15:45:32 -0800966 out.writeInt(mAutofillId.getVirtualChildIntId());
Adam Hedf596842018-10-04 15:59:57 -0700967 }
Felipe Lemea75333c2019-01-22 15:45:32 -0800968 // TODO(b/113593220): write session id as well
Adam Hedf596842018-10-04 15:59:57 -0700969 }
970 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_TYPE) != 0) {
971 out.writeInt(mAutofillType);
972 }
973 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_HINTS) != 0) {
974 out.writeStringArray(mAutofillHints);
975 }
976 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE) != 0) {
977 final AutofillValue sanitizedValue;
978 if (writeSensitive) {
979 sanitizedValue = mAutofillValue;
980 } else if (mAutofillOverlay != null && mAutofillOverlay.value != null) {
981 sanitizedValue = mAutofillOverlay.value;
982 } else {
983 sanitizedValue = null;
984 }
985 out.writeParcelable(sanitizedValue, 0);
986 }
987 if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
988 out.writeCharSequenceArray(mAutofillOptions);
989 }
990 if ((autofillFlags & AUTOFILL_FLAGS_HAS_HTML_INFO) != 0) {
991 out.writeParcelable((Parcelable) mHtmlInfo, 0);
992 }
993 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS) != 0) {
994 out.writeInt(mMinEms);
995 }
996 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_EMS) != 0) {
997 out.writeInt(mMaxEms);
998 }
999 if ((autofillFlags & AUTOFILL_FLAGS_HAS_MAX_TEXT_LENGTH) != 0) {
1000 out.writeInt(mMaxLength);
1001 }
1002 if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
1003 pwriter.writeString(mTextIdEntry);
1004 }
Felipe Leme29a5b0d2016-10-25 14:57:11 -07001005 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001006 if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
1007 out.writeInt(mX);
1008 out.writeInt(mY);
1009 out.writeInt(mWidth);
1010 out.writeInt(mHeight);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001011 } else {
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001012 out.writeInt((mY<<16) | mX);
1013 out.writeInt((mHeight<<16) | mWidth);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001014 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001015 if ((flags&FLAGS_HAS_SCROLL) != 0) {
1016 out.writeInt(mScrollX);
1017 out.writeInt(mScrollY);
1018 }
1019 if ((flags&FLAGS_HAS_MATRIX) != 0) {
1020 mMatrix.getValues(tmpMatrix);
1021 out.writeFloatArray(tmpMatrix);
1022 }
1023 if ((flags&FLAGS_HAS_ELEVATION) != 0) {
1024 out.writeFloat(mElevation);
1025 }
1026 if ((flags&FLAGS_HAS_ALPHA) != 0) {
1027 out.writeFloat(mAlpha);
1028 }
1029 if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
1030 TextUtils.writeToParcel(mContentDescription, out, 0);
1031 }
1032 if ((flags&FLAGS_HAS_TEXT) != 0) {
Felipe Leme0200d9e2017-01-24 15:10:26 -08001033 mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0, writeSensitive);
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001034 }
Felipe Leme16aafc32017-02-27 13:41:37 -08001035 if ((flags&FLAGS_HAS_INPUT_TYPE) != 0) {
1036 out.writeInt(mInputType);
1037 }
Felipe Lemec3241002017-02-15 12:55:11 -08001038 if ((flags&FLAGS_HAS_URL) != 0) {
Felipe Leme114a4412017-09-26 13:02:11 -07001039 out.writeString(mWebScheme);
Felipe Leme4711ed92017-04-21 16:47:18 -07001040 out.writeString(mWebDomain);
Felipe Lemec3241002017-02-15 12:55:11 -08001041 }
Felipe Lemeb4ca7012017-03-22 18:30:07 -07001042 if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) {
1043 out.writeParcelable(mLocaleList, 0);
1044 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001045 if ((flags&FLAGS_HAS_EXTRAS) != 0) {
1046 out.writeBundle(mExtras);
1047 }
Dianne Hackborn782d4982015-07-08 17:36:37 -07001048 return flags;
Dianne Hackborn16036f22015-06-22 14:05:51 -07001049 }
1050
1051 /**
1052 * Returns the ID associated with this view, as per {@link View#getId() View.getId()}.
1053 */
1054 public int getId() {
1055 return mId;
1056 }
1057
1058 /**
1059 * If {@link #getId()} is a resource identifier, this is the package name of that
1060 * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId}
1061 * for more information.
1062 */
1063 public String getIdPackage() {
1064 return mIdPackage;
1065 }
1066
1067 /**
1068 * If {@link #getId()} is a resource identifier, this is the type name of that
1069 * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId}
1070 * for more information.
1071 */
1072 public String getIdType() {
1073 return mIdType;
1074 }
1075
1076 /**
1077 * If {@link #getId()} is a resource identifier, this is the entry name of that
1078 * identifier. See {@link android.view.ViewStructure#setId ViewStructure.setId}
1079 * for more information.
1080 */
1081 public String getIdEntry() {
1082 return mIdEntry;
1083 }
1084
1085 /**
Felipe Leme640f30a2017-03-06 15:44:06 -08001086 * Gets the id that can be used to autofill the view contents.
1087 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001088 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
Felipe Leme30e9b262017-04-21 11:29:30 -07001089 *
1090 * @return id that can be used to autofill the view contents, or {@code null} if the
Felipe Leme2f6fc722017-05-31 11:57:46 -07001091 * structure was created for assist purposes.
Felipe Leme640f30a2017-03-06 15:44:06 -08001092 */
Felipe Leme30e9b262017-04-21 11:29:30 -07001093 @Nullable public AutofillId getAutofillId() {
Felipe Leme640f30a2017-03-06 15:44:06 -08001094 return mAutofillId;
1095 }
1096
1097 /**
koprivaa1a78482018-10-09 10:09:23 -07001098 * Gets the type of value that can be used to autofill the view contents.
Felipe Leme6d553872016-12-08 17:13:25 -08001099 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001100 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
Felipe Leme30e9b262017-04-21 11:29:30 -07001101 *
1102 * @return autofill type as defined by {@link View#getAutofillType()},
Felipe Leme2f6fc722017-05-31 11:57:46 -07001103 * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for assist purposes.
Felipe Leme6d553872016-12-08 17:13:25 -08001104 */
Felipe Leme8931e302017-03-06 13:44:35 -08001105 public @View.AutofillType int getAutofillType() {
1106 return mAutofillType;
Felipe Leme6d553872016-12-08 17:13:25 -08001107 }
1108
1109 /**
Felipe Leme640f30a2017-03-06 15:44:06 -08001110 * Describes the content of a view so that a autofill service can fill in the appropriate
Philip P. Moltmannba6f4622017-02-22 11:03:53 -08001111 * data.
1112 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001113 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
Felipe Leme30e9b262017-04-21 11:29:30 -07001114 * not for Assist - see {@link View#getAutofillHints()} for more info.
Philip P. Moltmannba6f4622017-02-22 11:03:53 -08001115 *
Felipe Leme30e9b262017-04-21 11:29:30 -07001116 * @return The autofill hints for this view, or {@code null} if the structure was created
Felipe Leme2f6fc722017-05-31 11:57:46 -07001117 * for assist purposes.
Philip P. Moltmannba6f4622017-02-22 11:03:53 -08001118 */
Felipe Lemeb1180212017-04-17 18:50:14 -07001119 @Nullable public String[] getAutofillHints() {
1120 return mAutofillHints;
1121 }
1122
1123 /**
koprivaa1a78482018-10-09 10:09:23 -07001124 * Gets the value of this view.
Felipe Leme0200d9e2017-01-24 15:10:26 -08001125 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001126 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1127 * not for assist purposes.
Felipe Leme30e9b262017-04-21 11:29:30 -07001128 *
1129 * @return the autofill value of this view, or {@code null} if the structure was created
Felipe Leme2f6fc722017-05-31 11:57:46 -07001130 * for assist purposes.
Felipe Leme0200d9e2017-01-24 15:10:26 -08001131 */
Felipe Leme30e9b262017-04-21 11:29:30 -07001132 @Nullable public AutofillValue getAutofillValue() {
Felipe Leme640f30a2017-03-06 15:44:06 -08001133 return mAutofillValue;
Felipe Leme0200d9e2017-01-24 15:10:26 -08001134 }
1135
Felipe Lemecde040a2017-03-31 17:26:34 -07001136 /** @hide **/
1137 public void setAutofillOverlay(AutofillOverlay overlay) {
1138 mAutofillOverlay = overlay;
1139 }
1140
Felipe Lemed09ccb82017-02-22 15:02:03 -08001141 /**
Felipe Leme30e9b262017-04-21 11:29:30 -07001142 * Gets the options that can be used to autofill this view.
Felipe Lemed09ccb82017-02-22 15:02:03 -08001143 *
Felipe Leme640f30a2017-03-06 15:44:06 -08001144 * <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate
1145 * the meaning of each possible value in the list.
Felipe Lemed09ccb82017-02-22 15:02:03 -08001146 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001147 * <p>It's relevant when the {@link AssistStructure} is used for autofill purposes, not
1148 * for assist purposes.
Felipe Leme30e9b262017-04-21 11:29:30 -07001149 *
1150 * @return the options that can be used to autofill this view, or {@code null} if the
Felipe Leme2f6fc722017-05-31 11:57:46 -07001151 * structure was created for assist purposes.
Felipe Lemed09ccb82017-02-22 15:02:03 -08001152 */
Felipe Leme30e9b262017-04-21 11:29:30 -07001153 @Nullable public CharSequence[] getAutofillOptions() {
Felipe Leme640f30a2017-03-06 15:44:06 -08001154 return mAutofillOptions;
Felipe Lemed09ccb82017-02-22 15:02:03 -08001155 }
1156
Felipe Leme16aafc32017-02-27 13:41:37 -08001157 /**
1158 * Gets the {@link android.text.InputType} bits of this structure.
1159 *
1160 * @return bits as defined by {@link android.text.InputType}.
1161 */
1162 public int getInputType() {
1163 return mInputType;
1164 }
1165
Felipe Leme0200d9e2017-01-24 15:10:26 -08001166 /** @hide */
1167 public boolean isSanitized() {
1168 return mSanitized;
1169 }
1170
1171 /**
Felipe Leme640f30a2017-03-06 15:44:06 -08001172 * Updates the {@link AutofillValue} of this structure.
Felipe Leme0200d9e2017-01-24 15:10:26 -08001173 *
1174 * <p>Should be used just before sending the structure to the
Felipe Leme640f30a2017-03-06 15:44:06 -08001175 * {@link android.service.autofill.AutofillService} for saving, since it will override the
Felipe Leme0200d9e2017-01-24 15:10:26 -08001176 * initial value.
1177 *
1178 * @hide
1179 */
Felipe Leme640f30a2017-03-06 15:44:06 -08001180 public void updateAutofillValue(AutofillValue value) {
1181 mAutofillValue = value;
Philip P. Moltmann96689032017-03-09 13:19:55 -08001182 if (value.isText()) {
Felipe Leme26675232017-06-19 09:45:48 -07001183 if (mText == null) {
1184 mText = new ViewNodeText();
1185 }
Philip P. Moltmann96689032017-03-09 13:19:55 -08001186 mText.mText = value.getTextValue();
Felipe Leme0200d9e2017-01-24 15:10:26 -08001187 }
1188 }
1189
1190 /**
Dianne Hackborn16036f22015-06-22 14:05:51 -07001191 * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
1192 */
1193 public int getLeft() {
1194 return mX;
1195 }
1196
1197 /**
1198 * Returns the top edge of this view, in pixels, relative to the top edge of its parent.
1199 */
1200 public int getTop() {
1201 return mY;
1202 }
1203
1204 /**
1205 * Returns the current X scroll offset of this view, as per
1206 * {@link android.view.View#getScrollX() View.getScrollX()}.
1207 */
1208 public int getScrollX() {
1209 return mScrollX;
1210 }
1211
1212 /**
1213 * Returns the current Y scroll offset of this view, as per
1214 * {@link android.view.View#getScrollX() View.getScrollY()}.
1215 */
1216 public int getScrollY() {
1217 return mScrollY;
1218 }
1219
1220 /**
1221 * Returns the width of this view, in pixels.
1222 */
1223 public int getWidth() {
1224 return mWidth;
1225 }
1226
1227 /**
1228 * Returns the height of this view, in pixels.
1229 */
1230 public int getHeight() {
1231 return mHeight;
1232 }
1233
1234 /**
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001235 * Returns the transformation that has been applied to this view, such as a translation
1236 * or scaling. The returned Matrix object is owned by ViewNode; do not modify it.
1237 * Returns null if there is no transformation applied to the view.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001238 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001239 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1240 * not for autofill purposes.
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001241 */
1242 public Matrix getTransformation() {
1243 return mMatrix;
1244 }
1245
1246 /**
1247 * Returns the visual elevation of the view, used for shadowing and other visual
1248 * characterstics, as set by {@link ViewStructure#setElevation
1249 * ViewStructure.setElevation(float)}.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001250 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001251 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1252 * not for autofill purposes.
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001253 */
1254 public float getElevation() {
1255 return mElevation;
1256 }
1257
1258 /**
1259 * Returns the alpha transformation of the view, used to reduce the overall opacity
1260 * of the view's contents, as set by {@link ViewStructure#setAlpha
1261 * ViewStructure.setAlpha(float)}.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001262 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001263 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1264 * not for autofill purposes.
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001265 */
1266 public float getAlpha() {
1267 return mAlpha;
1268 }
1269
1270 /**
Dianne Hackborn16036f22015-06-22 14:05:51 -07001271 * Returns the visibility mode of this view, as per
1272 * {@link android.view.View#getVisibility() View.getVisibility()}.
1273 */
1274 public int getVisibility() {
1275 return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
1276 }
1277
1278 /**
1279 * Returns true if assist data has been blocked starting at this node in the hierarchy.
1280 */
1281 public boolean isAssistBlocked() {
Dianne Hackbornfcbfeaf2015-07-15 11:25:55 -07001282 return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) != 0;
Dianne Hackborn16036f22015-06-22 14:05:51 -07001283 }
1284
1285 /**
1286 * Returns true if this node is in an enabled state.
1287 */
1288 public boolean isEnabled() {
1289 return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
1290 }
1291
1292 /**
1293 * Returns true if this node is clickable by the user.
1294 */
1295 public boolean isClickable() {
1296 return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
1297 }
1298
1299 /**
1300 * Returns true if this node can take input focus.
1301 */
1302 public boolean isFocusable() {
1303 return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
1304 }
1305
1306 /**
1307 * Returns true if this node currently had input focus at the time that the
1308 * structure was collected.
1309 */
1310 public boolean isFocused() {
1311 return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
1312 }
1313
1314 /**
1315 * Returns true if this node currently had accessibility focus at the time that the
1316 * structure was collected.
1317 */
1318 public boolean isAccessibilityFocused() {
1319 return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
1320 }
1321
1322 /**
1323 * Returns true if this node represents something that is checkable by the user.
1324 */
1325 public boolean isCheckable() {
1326 return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
1327 }
1328
1329 /**
1330 * Returns true if this node is currently in a checked state.
1331 */
1332 public boolean isChecked() {
1333 return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
1334 }
1335
1336 /**
1337 * Returns true if this node has currently been selected by the user.
1338 */
1339 public boolean isSelected() {
1340 return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
1341 }
1342
1343 /**
1344 * Returns true if this node has currently been activated by the user.
1345 */
1346 public boolean isActivated() {
1347 return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
1348 }
1349
1350 /**
Amith Yamasani858f98d2017-02-22 12:59:53 -08001351 * Returns true if this node is opaque.
1352 */
1353 public boolean isOpaque() { return (mFlags&ViewNode.FLAGS_OPAQUE) != 0; }
1354
1355 /**
Dianne Hackborn16036f22015-06-22 14:05:51 -07001356 * Returns true if this node is something the user can perform a long click/press on.
1357 */
1358 public boolean isLongClickable() {
1359 return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
1360 }
1361
1362 /**
1363 * Returns true if this node is something the user can perform a context click on.
1364 */
1365 public boolean isContextClickable() {
1366 return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
1367 }
1368
1369 /**
1370 * Returns the class name of the node's implementation, indicating its behavior.
1371 * For example, a button will report "android.widget.Button" meaning it behaves
1372 * like a {@link android.widget.Button}.
1373 */
1374 public String getClassName() {
1375 return mClassName;
1376 }
1377
1378 /**
1379 * Returns any content description associated with the node, which semantically describes
1380 * its purpose for accessibility and other uses.
1381 */
1382 public CharSequence getContentDescription() {
1383 return mContentDescription;
1384 }
1385
1386 /**
Felipe Leme4711ed92017-04-21 16:47:18 -07001387 * Returns the domain of the HTML document represented by this view.
Felipe Lemec3241002017-02-15 12:55:11 -08001388 *
Felipe Leme30e9b262017-04-21 11:29:30 -07001389 * <p>Typically used when the view associated with the view is a container for an HTML
Felipe Leme25bf7872017-03-28 15:32:29 -07001390 * document.
Felipe Lemebd271212017-02-22 09:05:07 -08001391 *
Felipe Leme62219032017-09-26 14:20:30 -07001392 * <p><b>Warning:</b> an autofill service cannot trust the value reported by this method
1393 * without verifing its authenticity&mdash;see the "Web security" section of
1394 * {@link android.service.autofill.AutofillService} for more details.
Felipe Leme4711ed92017-04-21 16:47:18 -07001395 *
1396 * @return domain-only part of the document. For example, if the full URL is
Felipe Leme114a4412017-09-26 13:02:11 -07001397 * {@code https://example.com/login?user=my_user}, it returns {@code example.com}.
Felipe Lemec3241002017-02-15 12:55:11 -08001398 */
Felipe Leme4711ed92017-04-21 16:47:18 -07001399 @Nullable public String getWebDomain() {
1400 return mWebDomain;
Felipe Lemec3241002017-02-15 12:55:11 -08001401 }
1402
1403 /**
Felipe Leme185de722018-02-13 17:25:44 -08001404 * @hide
1405 */
1406 public void setWebDomain(@Nullable String domain) {
1407 if (domain == null) return;
1408
1409 final Uri uri = Uri.parse(domain);
Felipe Leme98f4c692018-02-28 17:37:52 -08001410 if (uri == null) {
1411 // Cannot log domain because it could contain PII;
1412 Log.w(TAG, "Failed to parse web domain");
1413 return;
1414 }
Felipe Leme185de722018-02-13 17:25:44 -08001415 mWebScheme = uri.getScheme();
1416 mWebDomain = uri.getHost();
1417 }
1418
1419 /**
Felipe Leme114a4412017-09-26 13:02:11 -07001420 * Returns the scheme of the HTML document represented by this view.
1421 *
1422 * <p>Typically used when the view associated with the view is a container for an HTML
1423 * document.
1424 *
1425 * @return scheme-only part of the document. For example, if the full URL is
1426 * {@code https://example.com/login?user=my_user}, it returns {@code https}.
1427 */
1428 @Nullable public String getWebScheme() {
1429 return mWebScheme;
1430 }
1431
1432 /**
Felipe Leme30e9b262017-04-21 11:29:30 -07001433 * Returns the HTML properties associated with this view.
Felipe Leme25bf7872017-03-28 15:32:29 -07001434 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001435 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1436 * not for assist purposes.
Felipe Leme30e9b262017-04-21 11:29:30 -07001437 *
1438 * @return the HTML properties associated with this view, or {@code null} if the
Felipe Leme2f6fc722017-05-31 11:57:46 -07001439 * structure was created for assist purposes.
Felipe Leme25bf7872017-03-28 15:32:29 -07001440 */
Felipe Leme30e9b262017-04-21 11:29:30 -07001441 @Nullable public HtmlInfo getHtmlInfo() {
Felipe Leme25bf7872017-03-28 15:32:29 -07001442 return mHtmlInfo;
1443 }
1444
1445 /**
koprivaa1a78482018-10-09 10:09:23 -07001446 * Returns the list of locales associated with this view.
Felipe Lemeb4ca7012017-03-22 18:30:07 -07001447 */
Felipe Leme30e9b262017-04-21 11:29:30 -07001448 @Nullable public LocaleList getLocaleList() {
Felipe Lemeb4ca7012017-03-22 18:30:07 -07001449 return mLocaleList;
1450 }
1451
1452 /**
Dianne Hackborn16036f22015-06-22 14:05:51 -07001453 * Returns any text associated with the node that is displayed to the user, or null
1454 * if there is none.
1455 */
1456 public CharSequence getText() {
1457 return mText != null ? mText.mText : null;
1458 }
1459
1460 /**
1461 * If {@link #getText()} is non-null, this is where the current selection starts.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001462 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001463 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1464 * not for autofill purposes.
Dianne Hackborn16036f22015-06-22 14:05:51 -07001465 */
1466 public int getTextSelectionStart() {
1467 return mText != null ? mText.mTextSelectionStart : -1;
1468 }
1469
1470 /**
1471 * If {@link #getText()} is non-null, this is where the current selection starts.
1472 * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
1473 * indicating the cursor position.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001474 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001475 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1476 * not for autofill purposes.
Dianne Hackborn16036f22015-06-22 14:05:51 -07001477 */
1478 public int getTextSelectionEnd() {
1479 return mText != null ? mText.mTextSelectionEnd : -1;
1480 }
1481
1482 /**
1483 * If {@link #getText()} is non-null, this is the main text color associated with it.
1484 * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
1485 * Note that the text may also contain style spans that modify the color of specific
1486 * parts of the text.
1487 */
1488 public int getTextColor() {
1489 return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
1490 }
1491
1492 /**
1493 * If {@link #getText()} is non-null, this is the main text background color associated
1494 * with it.
1495 * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
1496 * Note that the text may also contain style spans that modify the color of specific
1497 * parts of the text.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001498 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001499 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1500 * not for autofill purposes.
Dianne Hackborn16036f22015-06-22 14:05:51 -07001501 */
1502 public int getTextBackgroundColor() {
1503 return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
1504 }
1505
1506 /**
1507 * If {@link #getText()} is non-null, this is the main text size (in pixels) associated
1508 * with it.
1509 * Note that the text may also contain style spans that modify the size of specific
1510 * parts of the text.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001511 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001512 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1513 * not for autofill purposes.
Dianne Hackborn16036f22015-06-22 14:05:51 -07001514 */
1515 public float getTextSize() {
1516 return mText != null ? mText.mTextSize : 0;
1517 }
1518
1519 /**
1520 * If {@link #getText()} is non-null, this is the main text style associated
1521 * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
1522 * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
1523 * {@link #TEXT_STYLE_UNDERLINE}.
1524 * Note that the text may also contain style spans that modify the style of specific
1525 * parts of the text.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001526 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001527 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1528 * not for autofill purposes.
Dianne Hackborn16036f22015-06-22 14:05:51 -07001529 */
1530 public int getTextStyle() {
1531 return mText != null ? mText.mTextStyle : 0;
1532 }
1533
1534 /**
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -07001535 * Return per-line offsets into the text returned by {@link #getText()}. Each entry
1536 * in the array is a formatted line of text, and the value it contains is the offset
1537 * into the text string where that line starts. May return null if there is no line
1538 * information.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001539 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001540 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1541 * not for autofill purposes.
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -07001542 */
1543 public int[] getTextLineCharOffsets() {
1544 return mText != null ? mText.mLineCharOffsets : null;
1545 }
1546
1547 /**
1548 * Return per-line baselines into the text returned by {@link #getText()}. Each entry
1549 * in the array is a formatted line of text, and the value it contains is the baseline
1550 * where that text appears in the view. May return null if there is no line
1551 * information.
Philip P. Moltmannc368a242017-05-04 12:29:59 -07001552 *
Felipe Leme2f6fc722017-05-31 11:57:46 -07001553 * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
1554 * not for autofill purposes.
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -07001555 */
1556 public int[] getTextLineBaselines() {
1557 return mText != null ? mText.mLineBaselines : null;
1558 }
1559
1560 /**
Felipe Leme5dc45ca2018-01-03 09:02:27 -08001561 * Gets the identifier used to set the text associated with this view.
1562 *
1563 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1564 * not for assist purposes.
1565 */
1566 @Nullable
1567 public String getTextIdEntry() {
1568 return mTextIdEntry;
1569 }
1570
1571 /**
Dianne Hackborn16036f22015-06-22 14:05:51 -07001572 * Return additional hint text associated with the node; this is typically used with
1573 * a node that takes user input, describing to the user what the input means.
1574 */
1575 public String getHint() {
1576 return mText != null ? mText.mHint : null;
1577 }
1578
1579 /**
1580 * Return a Bundle containing optional vendor-specific extension information.
1581 */
1582 public Bundle getExtras() {
1583 return mExtras;
1584 }
1585
1586 /**
1587 * Return the number of children this node has.
1588 */
1589 public int getChildCount() {
1590 return mChildren != null ? mChildren.length : 0;
1591 }
1592
1593 /**
1594 * Return a child of this node, given an index value from 0 to
1595 * {@link #getChildCount()}-1.
1596 */
1597 public ViewNode getChildAt(int index) {
1598 return mChildren[index];
1599 }
Felipe Lemeaa7e2292017-10-05 18:19:48 -07001600
1601 /**
1602 * Returns the minimum width in ems of the text associated with this node, or {@code -1}
1603 * if not supported by the node.
1604 *
1605 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1606 * not for assist purposes.
1607 */
1608 public int getMinTextEms() {
1609 return mMinEms;
1610 }
1611
1612 /**
1613 * Returns the maximum width in ems of the text associated with this node, or {@code -1}
1614 * if not supported by the node.
1615 *
1616 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1617 * not for assist purposes.
1618 */
1619 public int getMaxTextEms() {
1620 return mMaxEms;
1621 }
1622
1623 /**
1624 * Returns the maximum length of the text associated with this node node, or {@code -1}
1625 * if not supported by the node or not set.
1626 *
1627 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
1628 * not for assist purposes.
1629 */
1630 public int getMaxTextLength() {
1631 return mMaxLength;
1632 }
felipeal53308c12018-02-07 14:43:30 +01001633
1634 /**
1635 * Gets the {@link View#setImportantForAutofill(int) importantForAutofill mode} of
1636 * the view associated with this node.
1637 *
1638 * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
1639 */
1640 public @AutofillImportance int getImportantForAutofill() {
1641 return mImportantForAutofill;
1642 }
Dianne Hackborn16036f22015-06-22 14:05:51 -07001643 }
1644
Felipe Lemecde040a2017-03-31 17:26:34 -07001645 /**
1646 * POJO used to override some autofill-related values when the node is parcelized.
1647 *
1648 * @hide
1649 */
1650 static public class AutofillOverlay {
1651 public boolean focused;
1652 public AutofillValue value;
1653 }
1654
Dianne Hackborn8ecf16d2015-06-23 13:09:21 -07001655 static class ViewNodeBuilder extends ViewStructure {
Dianne Hackborn16036f22015-06-22 14:05:51 -07001656 final AssistStructure mAssist;
1657 final ViewNode mNode;
1658 final boolean mAsync;
1659
Felipe Leme33791fd2017-02-16 08:07:56 -08001660 ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
Dianne Hackborn16036f22015-06-22 14:05:51 -07001661 mAssist = assist;
1662 mNode = node;
1663 mAsync = async;
1664 }
1665
1666 @Override
1667 public void setId(int id, String packageName, String typeName, String entryName) {
1668 mNode.mId = id;
1669 mNode.mIdPackage = packageName;
1670 mNode.mIdType = typeName;
1671 mNode.mIdEntry = entryName;
1672 }
1673
1674 @Override
1675 public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
1676 mNode.mX = left;
1677 mNode.mY = top;
1678 mNode.mScrollX = scrollX;
1679 mNode.mScrollY = scrollY;
1680 mNode.mWidth = width;
1681 mNode.mHeight = height;
1682 }
1683
1684 @Override
Dianne Hackborn70d8be72015-06-23 19:33:02 +00001685 public void setTransformation(Matrix matrix) {
1686 if (matrix == null) {
1687 mNode.mMatrix = null;
1688 } else {
1689 mNode.mMatrix = new Matrix(matrix);
1690 }
1691 }
1692
1693 @Override
1694 public void setElevation(float elevation) {
1695 mNode.mElevation = elevation;
1696 }
1697
1698 @Override
1699 public void setAlpha(float alpha) {
1700 mNode.mAlpha = alpha;
1701 }
1702
1703 @Override
Dianne Hackborn16036f22015-06-22 14:05:51 -07001704 public void setVisibility(int visibility) {
Felipe Leme93ffb982019-01-08 09:17:14 -08001705 mNode.mFlags = (mNode.mFlags & ~ViewNode.FLAGS_VISIBILITY_MASK)
1706 | (visibility & ViewNode.FLAGS_VISIBILITY_MASK);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001707 }
1708
1709 @Override
1710 public void setAssistBlocked(boolean state) {
1711 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED)
Dianne Hackbornafb308d2015-07-31 13:10:55 -07001712 | (state ? ViewNode.FLAGS_ASSIST_BLOCKED : 0);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001713 }
1714
1715 @Override
1716 public void setEnabled(boolean state) {
1717 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED)
1718 | (state ? 0 : ViewNode.FLAGS_DISABLED);
1719 }
1720
1721 @Override
1722 public void setClickable(boolean state) {
1723 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE)
1724 | (state ? ViewNode.FLAGS_CLICKABLE : 0);
1725 }
1726
1727 @Override
1728 public void setLongClickable(boolean state) {
1729 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE)
1730 | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0);
1731 }
1732
1733 @Override
1734 public void setContextClickable(boolean state) {
1735 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE)
1736 | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0);
1737 }
1738
1739 @Override
1740 public void setFocusable(boolean state) {
1741 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
1742 | (state ? ViewNode.FLAGS_FOCUSABLE : 0);
1743 }
1744
1745 @Override
1746 public void setFocused(boolean state) {
1747 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED)
1748 | (state ? ViewNode.FLAGS_FOCUSED : 0);
1749 }
1750
1751 @Override
1752 public void setAccessibilityFocused(boolean state) {
1753 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED)
1754 | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0);
1755 }
1756
1757 @Override
1758 public void setCheckable(boolean state) {
1759 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE)
1760 | (state ? ViewNode.FLAGS_CHECKABLE : 0);
1761 }
1762
1763 @Override
1764 public void setChecked(boolean state) {
1765 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED)
1766 | (state ? ViewNode.FLAGS_CHECKED : 0);
1767 }
1768
1769 @Override
1770 public void setSelected(boolean state) {
1771 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED)
1772 | (state ? ViewNode.FLAGS_SELECTED : 0);
1773 }
1774
1775 @Override
1776 public void setActivated(boolean state) {
1777 mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED)
1778 | (state ? ViewNode.FLAGS_ACTIVATED : 0);
1779 }
1780
1781 @Override
Amith Yamasani858f98d2017-02-22 12:59:53 -08001782 public void setOpaque(boolean opaque) {
1783 mNode.mFlags = (mNode.mFlags & ~ViewNode.FLAGS_OPAQUE)
1784 | (opaque ? ViewNode.FLAGS_OPAQUE : 0);
1785 }
1786
1787 @Override
Dianne Hackborn16036f22015-06-22 14:05:51 -07001788 public void setClassName(String className) {
1789 mNode.mClassName = className;
1790 }
1791
1792 @Override
1793 public void setContentDescription(CharSequence contentDescription) {
1794 mNode.mContentDescription = contentDescription;
1795 }
1796
1797 private final ViewNodeText getNodeText() {
1798 if (mNode.mText != null) {
1799 return mNode.mText;
1800 }
1801 mNode.mText = new ViewNodeText();
1802 return mNode.mText;
1803 }
1804
1805 @Override
1806 public void setText(CharSequence text) {
1807 ViewNodeText t = getNodeText();
Felipe Lemea8fce3b2017-04-04 14:22:12 -07001808 t.mText = TextUtils.trimNoCopySpans(text);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001809 t.mTextSelectionStart = t.mTextSelectionEnd = -1;
1810 }
1811
1812 @Override
1813 public void setText(CharSequence text, int selectionStart, int selectionEnd) {
1814 ViewNodeText t = getNodeText();
Felipe Lemea8fce3b2017-04-04 14:22:12 -07001815 t.mText = TextUtils.trimNoCopySpans(text);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001816 t.mTextSelectionStart = selectionStart;
1817 t.mTextSelectionEnd = selectionEnd;
1818 }
1819
1820 @Override
1821 public void setTextStyle(float size, int fgColor, int bgColor, int style) {
1822 ViewNodeText t = getNodeText();
1823 t.mTextColor = fgColor;
1824 t.mTextBackgroundColor = bgColor;
1825 t.mTextSize = size;
1826 t.mTextStyle = style;
1827 }
1828
1829 @Override
Dianne Hackborn6f0fdc42015-07-07 14:29:36 -07001830 public void setTextLines(int[] charOffsets, int[] baselines) {
1831 ViewNodeText t = getNodeText();
1832 t.mLineCharOffsets = charOffsets;
1833 t.mLineBaselines = baselines;
1834 }
1835
1836 @Override
Felipe Leme5dc45ca2018-01-03 09:02:27 -08001837 public void setTextIdEntry(@NonNull String entryName) {
1838 mNode.mTextIdEntry = Preconditions.checkNotNull(entryName);
1839 }
1840
1841 @Override
Dianne Hackborn16036f22015-06-22 14:05:51 -07001842 public void setHint(CharSequence hint) {
1843 getNodeText().mHint = hint != null ? hint.toString() : null;
1844 }
1845
1846 @Override
1847 public CharSequence getText() {
1848 return mNode.mText != null ? mNode.mText.mText : null;
1849 }
1850
1851 @Override
1852 public int getTextSelectionStart() {
1853 return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1;
1854 }
1855
1856 @Override
1857 public int getTextSelectionEnd() {
1858 return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1;
1859 }
1860
1861 @Override
1862 public CharSequence getHint() {
1863 return mNode.mText != null ? mNode.mText.mHint : null;
1864 }
1865
1866 @Override
1867 public Bundle getExtras() {
1868 if (mNode.mExtras != null) {
1869 return mNode.mExtras;
1870 }
1871 mNode.mExtras = new Bundle();
1872 return mNode.mExtras;
1873 }
1874
1875 @Override
1876 public boolean hasExtras() {
1877 return mNode.mExtras != null;
1878 }
1879
1880 @Override
1881 public void setChildCount(int num) {
1882 mNode.mChildren = new ViewNode[num];
1883 }
1884
1885 @Override
1886 public int addChildCount(int num) {
1887 if (mNode.mChildren == null) {
1888 setChildCount(num);
1889 return 0;
1890 }
1891 final int start = mNode.mChildren.length;
1892 ViewNode[] newArray = new ViewNode[start + num];
1893 System.arraycopy(mNode.mChildren, 0, newArray, 0, start);
1894 mNode.mChildren = newArray;
1895 return start;
1896 }
1897
1898 @Override
1899 public int getChildCount() {
1900 return mNode.mChildren != null ? mNode.mChildren.length : 0;
1901 }
1902
Felipe Lemef8a81742017-03-17 18:05:01 -07001903 @Override
Felipe Lemef8a81742017-03-17 18:05:01 -07001904 public ViewStructure newChild(int index) {
Dianne Hackborn16036f22015-06-22 14:05:51 -07001905 ViewNode node = new ViewNode();
1906 mNode.mChildren[index] = node;
Felipe Leme33791fd2017-02-16 08:07:56 -08001907 return new ViewNodeBuilder(mAssist, node, false);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001908 }
1909
Felipe Lemef8a81742017-03-17 18:05:01 -07001910 @Override
1911 public ViewStructure asyncNewChild(int index) {
Dianne Hackborn16036f22015-06-22 14:05:51 -07001912 synchronized (mAssist) {
1913 ViewNode node = new ViewNode();
1914 mNode.mChildren[index] = node;
Felipe Leme33791fd2017-02-16 08:07:56 -08001915 ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
Dianne Hackborn16036f22015-06-22 14:05:51 -07001916 mAssist.mPendingAsyncChildren.add(builder);
1917 return builder;
1918 }
1919 }
1920
1921 @Override
1922 public void asyncCommit() {
1923 synchronized (mAssist) {
1924 if (!mAsync) {
1925 throw new IllegalStateException("Child " + this
Dianne Hackborn8ecf16d2015-06-23 13:09:21 -07001926 + " was not created with ViewStructure.asyncNewChild");
Dianne Hackborn16036f22015-06-22 14:05:51 -07001927 }
1928 if (!mAssist.mPendingAsyncChildren.remove(this)) {
1929 throw new IllegalStateException("Child " + this + " already committed");
1930 }
1931 mAssist.notifyAll();
1932 }
1933 }
1934
1935 @Override
1936 public Rect getTempRect() {
1937 return mAssist.mTmpRect;
1938 }
Felipe Leme29a5b0d2016-10-25 14:57:11 -07001939
1940 @Override
Felipe Lemee4f30652017-04-25 10:21:45 -07001941 public void setAutofillId(@NonNull AutofillId id) {
1942 mNode.mAutofillId = id;
1943 }
1944
1945 @Override
1946 public void setAutofillId(@NonNull AutofillId parentId, int virtualId) {
1947 mNode.mAutofillId = new AutofillId(parentId, virtualId);
Felipe Leme29a5b0d2016-10-25 14:57:11 -07001948 }
Felipe Leme6d553872016-12-08 17:13:25 -08001949
1950 @Override
Felipe Leme640f30a2017-03-06 15:44:06 -08001951 public AutofillId getAutofillId() {
1952 return mNode.mAutofillId;
Felipe Leme8931e302017-03-06 13:44:35 -08001953 }
1954
1955 @Override
1956 public void setAutofillType(@View.AutofillType int type) {
1957 mNode.mAutofillType = type;
Felipe Leme6d553872016-12-08 17:13:25 -08001958 }
1959
Felipe Leme0200d9e2017-01-24 15:10:26 -08001960 @Override
Philip P. Moltmann81192b42017-03-29 13:58:59 -07001961 public void setAutofillHints(@Nullable String[] hints) {
1962 mNode.mAutofillHints = hints;
Philip P. Moltmannba6f4622017-02-22 11:03:53 -08001963 }
1964
1965 @Override
Felipe Leme640f30a2017-03-06 15:44:06 -08001966 public void setAutofillValue(AutofillValue value) {
1967 mNode.mAutofillValue = value;
Felipe Leme0200d9e2017-01-24 15:10:26 -08001968 }
1969
Felipe Lemed09ccb82017-02-22 15:02:03 -08001970 @Override
Felipe Leme7e4c2052017-04-18 09:45:58 -07001971 public void setAutofillOptions(CharSequence[] options) {
Felipe Leme640f30a2017-03-06 15:44:06 -08001972 mNode.mAutofillOptions = options;
Felipe Lemed09ccb82017-02-22 15:02:03 -08001973 }
1974
Felipe Leme16aafc32017-02-27 13:41:37 -08001975 @Override
felipeal53308c12018-02-07 14:43:30 +01001976 public void setImportantForAutofill(@AutofillImportance int mode) {
1977 mNode.mImportantForAutofill = mode;
1978 }
1979
1980 @Override
Felipe Leme16aafc32017-02-27 13:41:37 -08001981 public void setInputType(int inputType) {
1982 mNode.mInputType = inputType;
1983 }
1984
Felipe Leme0200d9e2017-01-24 15:10:26 -08001985 @Override
Felipe Lemeaa7e2292017-10-05 18:19:48 -07001986 public void setMinTextEms(int minEms) {
1987 mNode.mMinEms = minEms;
1988 }
1989
1990 @Override
1991 public void setMaxTextEms(int maxEms) {
1992 mNode.mMaxEms = maxEms;
1993 }
1994
1995 @Override
1996 public void setMaxTextLength(int maxLength) {
1997 mNode.mMaxLength = maxLength;
1998 }
1999
2000 @Override
Felipe Lemec9a19b12017-03-13 18:05:22 -07002001 public void setDataIsSensitive(boolean sensitive) {
2002 mNode.mSanitized = !sensitive;
Felipe Leme0200d9e2017-01-24 15:10:26 -08002003 }
Felipe Lemec3241002017-02-15 12:55:11 -08002004
2005 @Override
Felipe Leme4711ed92017-04-21 16:47:18 -07002006 public void setWebDomain(@Nullable String domain) {
Felipe Leme185de722018-02-13 17:25:44 -08002007 mNode.setWebDomain(domain);
Felipe Lemec3241002017-02-15 12:55:11 -08002008 }
Felipe Lemeb4ca7012017-03-22 18:30:07 -07002009
2010 @Override
2011 public void setLocaleList(LocaleList localeList) {
2012 mNode.mLocaleList = localeList;
2013 }
Felipe Leme25bf7872017-03-28 15:32:29 -07002014
2015 @Override
2016 public HtmlInfo.Builder newHtmlInfoBuilder(@NonNull String tagName) {
2017 return new HtmlInfoNodeBuilder(tagName);
2018 }
2019
2020 @Override
2021 public void setHtmlInfo(@NonNull HtmlInfo htmlInfo) {
2022 mNode.mHtmlInfo = htmlInfo;
2023 }
2024 }
2025
2026 private static final class HtmlInfoNode extends HtmlInfo implements Parcelable {
2027 private final String mTag;
2028 private final String[] mNames;
2029 private final String[] mValues;
2030
2031 // Not parcelable
2032 private ArrayList<Pair<String, String>> mAttributes;
2033
2034 private HtmlInfoNode(HtmlInfoNodeBuilder builder) {
2035 mTag = builder.mTag;
2036 if (builder.mNames == null) {
2037 mNames = null;
2038 mValues = null;
2039 } else {
2040 mNames = new String[builder.mNames.size()];
2041 mValues = new String[builder.mValues.size()];
2042 builder.mNames.toArray(mNames);
2043 builder.mValues.toArray(mValues);
2044 }
2045 }
2046
2047 @Override
2048 public String getTag() {
2049 return mTag;
2050 }
2051
2052 @Override
Felipe Leme09a70622017-04-27 15:24:19 -07002053 public List<Pair<String, String>> getAttributes() {
Felipe Leme25bf7872017-03-28 15:32:29 -07002054 if (mAttributes == null && mNames != null) {
2055 mAttributes = new ArrayList<>(mNames.length);
2056 for (int i = 0; i < mNames.length; i++) {
2057 final Pair<String, String> pair = new Pair<>(mNames[i], mValues[i]);
2058 mAttributes.add(i, pair);
2059 }
2060 }
2061 return mAttributes;
2062 }
2063
2064 @Override
2065 public int describeContents() {
2066 return 0;
2067 }
2068
2069 @Override
2070 public void writeToParcel(Parcel parcel, int flags) {
2071 parcel.writeString(mTag);
2072 parcel.writeStringArray(mNames);
2073 parcel.writeStringArray(mValues);
2074 }
2075
2076 @SuppressWarnings("hiding")
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07002077 public static final @android.annotation.NonNull Creator<HtmlInfoNode> CREATOR = new Creator<HtmlInfoNode>() {
Felipe Leme25bf7872017-03-28 15:32:29 -07002078 @Override
2079 public HtmlInfoNode createFromParcel(Parcel parcel) {
2080 // Always go through the builder to ensure the data ingested by
2081 // the system obeys the contract of the builder to avoid attacks
2082 // using specially crafted parcels.
2083 final String tag = parcel.readString();
2084 final HtmlInfoNodeBuilder builder = new HtmlInfoNodeBuilder(tag);
2085 final String[] names = parcel.readStringArray();
2086 final String[] values = parcel.readStringArray();
2087 if (names != null && values != null) {
2088 if (names.length != values.length) {
2089 Log.w(TAG, "HtmlInfo attributes mismatch: names=" + names.length
2090 + ", values=" + values.length);
2091 } else {
2092 for (int i = 0; i < names.length; i++) {
2093 builder.addAttribute(names[i], values[i]);
2094 }
2095 }
2096 }
2097 return builder.build();
2098 }
2099
2100 @Override
2101 public HtmlInfoNode[] newArray(int size) {
2102 return new HtmlInfoNode[size];
2103 }
2104 };
2105 }
2106
2107 private static final class HtmlInfoNodeBuilder extends HtmlInfo.Builder {
2108 private final String mTag;
2109 private ArrayList<String> mNames;
2110 private ArrayList<String> mValues;
2111
2112 HtmlInfoNodeBuilder(String tag) {
2113 mTag = tag;
2114 }
2115
2116 @Override
2117 public Builder addAttribute(String name, String value) {
2118 if (mNames == null) {
2119 mNames = new ArrayList<>();
2120 mValues = new ArrayList<>();
2121 }
2122 mNames.add(name);
2123 mValues.add(value);
2124 return this;
2125 }
2126
2127 @Override
2128 public HtmlInfoNode build() {
2129 return new HtmlInfoNode(this);
2130 }
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002131 }
2132
2133 /** @hide */
Svet Ganovfd31f852017-04-26 15:54:27 -07002134 public AssistStructure(Activity activity, boolean forAutoFill, int flags) {
Dianne Hackborn16036f22015-06-22 14:05:51 -07002135 mHaveData = true;
Felipe Leme0aa4c502017-04-26 12:36:01 -07002136 mFlags = flags;
Dianne Hackborn16036f22015-06-22 14:05:51 -07002137 ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
2138 activity.getActivityToken());
2139 for (int i=0; i<views.size(); i++) {
2140 ViewRootImpl root = views.get(i);
Felipe Leme5cfcb5c2017-07-20 15:05:57 -07002141 if (root.getView() == null) {
2142 Log.w(TAG, "Skipping window with dettached view: " + root.getTitle());
2143 continue;
2144 }
Svet Ganovfd31f852017-04-26 15:54:27 -07002145 mWindowNodes.add(new WindowNode(this, root, forAutoFill, flags));
Dianne Hackborn16036f22015-06-22 14:05:51 -07002146 }
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002147 }
2148
Dianne Hackborn16036f22015-06-22 14:05:51 -07002149 public AssistStructure() {
2150 mHaveData = true;
Felipe Leme0aa4c502017-04-26 12:36:01 -07002151 mFlags = 0;
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002152 }
2153
Dianne Hackborn16036f22015-06-22 14:05:51 -07002154 /** @hide */
2155 public AssistStructure(Parcel in) {
Winson Chung48b25652018-10-22 14:04:30 -07002156 mTaskId = in.readInt();
2157 mActivityComponent = ComponentName.readFromParcel(in);
Amith Yamasani858f98d2017-02-22 12:59:53 -08002158 mIsHomeActivity = in.readInt() == 1;
Dianne Hackborn16036f22015-06-22 14:05:51 -07002159 mReceiveChannel = in.readStrongBinder();
2160 }
2161
Felipe Leme0200d9e2017-01-24 15:10:26 -08002162 /**
2163 * Helper method used to sanitize the structure before it's written to a parcel.
2164 *
Felipe Leme640f30a2017-03-06 15:44:06 -08002165 * <p>Used just on autofill.
Felipe Leme0200d9e2017-01-24 15:10:26 -08002166 * @hide
2167 */
2168 public void sanitizeForParceling(boolean sanitize) {
2169 mSanitizeOnWrite = sanitize;
2170 }
2171
Dianne Hackborn16036f22015-06-22 14:05:51 -07002172 /** @hide */
Felipe Lemebc561eb2017-05-11 17:46:36 -07002173 public void dump(boolean showSensitive) {
Felipe Leme0200d9e2017-01-24 15:10:26 -08002174 if (mActivityComponent == null) {
2175 Log.i(TAG, "dump(): calling ensureData() first");
2176 ensureData();
2177 }
Winson Chung48b25652018-10-22 14:04:30 -07002178 Log.i(TAG, "Task id: " + mTaskId);
2179 Log.i(TAG, "Activity: " + (mActivityComponent != null
2180 ? mActivityComponent.flattenToShortString()
2181 : null));
Felipe Leme0200d9e2017-01-24 15:10:26 -08002182 Log.i(TAG, "Sanitize on write: " + mSanitizeOnWrite);
Felipe Leme0aa4c502017-04-26 12:36:01 -07002183 Log.i(TAG, "Flags: " + mFlags);
Dianne Hackborn16036f22015-06-22 14:05:51 -07002184 final int N = getWindowNodeCount();
2185 for (int i=0; i<N; i++) {
2186 WindowNode node = getWindowNodeAt(i);
2187 Log.i(TAG, "Window #" + i + " [" + node.getLeft() + "," + node.getTop()
2188 + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getTitle());
Felipe Lemebc561eb2017-05-11 17:46:36 -07002189 dump(" ", node.getRootViewNode(), showSensitive);
Dianne Hackborn16036f22015-06-22 14:05:51 -07002190 }
2191 }
2192
Felipe Lemebc561eb2017-05-11 17:46:36 -07002193 void dump(String prefix, ViewNode node, boolean showSensitive) {
Dianne Hackborn16036f22015-06-22 14:05:51 -07002194 Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop()
2195 + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName());
2196 int id = node.getId();
2197 if (id != 0) {
2198 StringBuilder sb = new StringBuilder();
2199 sb.append(prefix); sb.append(" ID: #"); sb.append(Integer.toHexString(id));
2200 String entry = node.getIdEntry();
2201 if (entry != null) {
2202 String type = node.getIdType();
2203 String pkg = node.getIdPackage();
2204 sb.append(" "); sb.append(pkg); sb.append(":"); sb.append(type);
2205 sb.append("/"); sb.append(entry);
2206 }
2207 Log.i(TAG, sb.toString());
2208 }
2209 int scrollX = node.getScrollX();
2210 int scrollY = node.getScrollY();
2211 if (scrollX != 0 || scrollY != 0) {
2212 Log.i(TAG, prefix + " Scroll: " + scrollX + "," + scrollY);
2213 }
Dianne Hackborn70d8be72015-06-23 19:33:02 +00002214 Matrix matrix = node.getTransformation();
2215 if (matrix != null) {
2216 Log.i(TAG, prefix + " Transformation: " + matrix);
2217 }
2218 float elevation = node.getElevation();
2219 if (elevation != 0) {
2220 Log.i(TAG, prefix + " Elevation: " + elevation);
2221 }
2222 float alpha = node.getAlpha();
2223 if (alpha != 0) {
2224 Log.i(TAG, prefix + " Alpha: " + elevation);
2225 }
Dianne Hackborn16036f22015-06-22 14:05:51 -07002226 CharSequence contentDescription = node.getContentDescription();
2227 if (contentDescription != null) {
2228 Log.i(TAG, prefix + " Content description: " + contentDescription);
2229 }
2230 CharSequence text = node.getText();
2231 if (text != null) {
Felipe Lemebc561eb2017-05-11 17:46:36 -07002232 final String safeText = node.isSanitized() || showSensitive ? text.toString()
2233 : "REDACTED[" + text.length() + " chars]";
Dianne Hackborn16036f22015-06-22 14:05:51 -07002234 Log.i(TAG, prefix + " Text (sel " + node.getTextSelectionStart() + "-"
Felipe Lemebc561eb2017-05-11 17:46:36 -07002235 + node.getTextSelectionEnd() + "): " + safeText);
Dianne Hackborn16036f22015-06-22 14:05:51 -07002236 Log.i(TAG, prefix + " Text size: " + node.getTextSize() + " , style: #"
2237 + node.getTextStyle());
2238 Log.i(TAG, prefix + " Text color fg: #" + Integer.toHexString(node.getTextColor())
2239 + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
Felipe Lemebc561eb2017-05-11 17:46:36 -07002240 Log.i(TAG, prefix + " Input type: " + node.getInputType());
Felipe Leme5dc45ca2018-01-03 09:02:27 -08002241 Log.i(TAG, prefix + " Resource id: " + node.getTextIdEntry());
Dianne Hackborn16036f22015-06-22 14:05:51 -07002242 }
Felipe Leme4711ed92017-04-21 16:47:18 -07002243 String webDomain = node.getWebDomain();
2244 if (webDomain != null) {
2245 Log.i(TAG, prefix + " Web domain: " + webDomain);
Felipe Lemec3241002017-02-15 12:55:11 -08002246 }
Felipe Leme25bf7872017-03-28 15:32:29 -07002247 HtmlInfo htmlInfo = node.getHtmlInfo();
2248 if (htmlInfo != null) {
2249 Log.i(TAG, prefix + " HtmlInfo: tag=" + htmlInfo.getTag()
2250 + ", attr="+ htmlInfo.getAttributes());
2251 }
2252
Felipe Lemeb4ca7012017-03-22 18:30:07 -07002253 LocaleList localeList = node.getLocaleList();
2254 if (localeList != null) {
2255 Log.i(TAG, prefix + " LocaleList: " + localeList);
2256 }
Dianne Hackborn16036f22015-06-22 14:05:51 -07002257 String hint = node.getHint();
2258 if (hint != null) {
2259 Log.i(TAG, prefix + " Hint: " + hint);
2260 }
2261 Bundle extras = node.getExtras();
2262 if (extras != null) {
2263 Log.i(TAG, prefix + " Extras: " + extras);
2264 }
Dianne Hackbornafb308d2015-07-31 13:10:55 -07002265 if (node.isAssistBlocked()) {
2266 Log.i(TAG, prefix + " BLOCKED");
2267 }
Felipe Leme640f30a2017-03-06 15:44:06 -08002268 AutofillId autofillId = node.getAutofillId();
2269 if (autofillId == null) {
2270 Log.i(TAG, prefix + " NO autofill ID");
Felipe Leme0200d9e2017-01-24 15:10:26 -08002271 } else {
Felipe Lemece470002018-07-11 14:19:02 -07002272 Log.i(TAG, prefix + " Autofill info: id= " + autofillId
Felipe Leme8931e302017-03-06 13:44:35 -08002273 + ", type=" + node.getAutofillType()
Felipe Leme640f30a2017-03-06 15:44:06 -08002274 + ", options=" + Arrays.toString(node.getAutofillOptions())
Felipe Leme30e9b262017-04-21 11:29:30 -07002275 + ", hints=" + Arrays.toString(node.getAutofillHints())
Felipe Leme640f30a2017-03-06 15:44:06 -08002276 + ", value=" + node.getAutofillValue()
felipeal53308c12018-02-07 14:43:30 +01002277 + ", sanitized=" + node.isSanitized()
Felipe Lemece470002018-07-11 14:19:02 -07002278 + ", important=" + node.getImportantForAutofill());
Felipe Leme0200d9e2017-01-24 15:10:26 -08002279 }
2280
Dianne Hackborn16036f22015-06-22 14:05:51 -07002281 final int NCHILDREN = node.getChildCount();
2282 if (NCHILDREN > 0) {
2283 Log.i(TAG, prefix + " Children:");
2284 String cprefix = prefix + " ";
2285 for (int i=0; i<NCHILDREN; i++) {
2286 ViewNode cnode = node.getChildAt(i);
Felipe Lemebc561eb2017-05-11 17:46:36 -07002287 dump(cprefix, cnode, showSensitive);
Dianne Hackborn16036f22015-06-22 14:05:51 -07002288 }
2289 }
2290 }
2291
2292 /**
Winson Chung48b25652018-10-22 14:04:30 -07002293 * Sets the task id is associated with the activity from which this AssistStructure was
2294 * generated.
2295 * @hide
Dianne Hackborn16036f22015-06-22 14:05:51 -07002296 */
Winson Chung48b25652018-10-22 14:04:30 -07002297 public void setTaskId(int taskId) {
2298 mTaskId = taskId;
Dianne Hackborn16036f22015-06-22 14:05:51 -07002299 }
2300
Felipe Leme3f3fa1b2017-11-30 17:41:57 -08002301 /**
Winson Chung48b25652018-10-22 14:04:30 -07002302 * @return The task id for the associated activity.
2303 * @hide
2304 */
2305 public int getTaskId() {
2306 return mTaskId;
2307 }
2308
2309 /**
2310 * Sets the activity that is associated with this AssistStructure.
Felipe Leme3f3fa1b2017-11-30 17:41:57 -08002311 * @hide
2312 */
2313 public void setActivityComponent(ComponentName componentName) {
Felipe Leme3f3fa1b2017-11-30 17:41:57 -08002314 mActivityComponent = componentName;
2315 }
2316
Winson Chung48b25652018-10-22 14:04:30 -07002317 /**
2318 * Return the activity this AssistStructure came from.
2319 */
2320 public ComponentName getActivityComponent() {
2321 return mActivityComponent;
2322 }
2323
Felipe Leme0aa4c502017-04-26 12:36:01 -07002324 /** @hide */
2325 public int getFlags() {
2326 return mFlags;
2327 }
2328
Dianne Hackborn16036f22015-06-22 14:05:51 -07002329 /**
Amith Yamasani858f98d2017-02-22 12:59:53 -08002330 * Returns whether the activity associated with this AssistStructure was the home activity
Amith Yamasani86687822017-04-26 11:35:15 -07002331 * (Launcher) at the time the assist data was acquired.
Amith Yamasani858f98d2017-02-22 12:59:53 -08002332 * @return Whether the activity was the home activity.
Amith Yamasani86687822017-04-26 11:35:15 -07002333 * @see android.content.Intent#CATEGORY_HOME
Amith Yamasani858f98d2017-02-22 12:59:53 -08002334 */
2335 public boolean isHomeActivity() {
2336 return mIsHomeActivity;
2337 }
2338
2339 /**
Dianne Hackborn16036f22015-06-22 14:05:51 -07002340 * Return the number of window contents that have been collected in this assist data.
2341 */
2342 public int getWindowNodeCount() {
2343 ensureData();
2344 return mWindowNodes.size();
2345 }
2346
2347 /**
2348 * Return one of the windows in the assist data.
2349 * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1.
2350 */
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002351 public WindowNode getWindowNodeAt(int index) {
Dianne Hackborn16036f22015-06-22 14:05:51 -07002352 ensureData();
2353 return mWindowNodes.get(index);
2354 }
2355
Felipe Leme849df8f2018-03-07 09:56:41 -08002356 // TODO(b/35708678): temporary method that disable one-way warning flag on binder.
2357 /** @hide */
2358 public void ensureDataForAutofill() {
2359 if (mHaveData) {
2360 return;
2361 }
2362 mHaveData = true;
2363 Binder.allowBlocking(mReceiveChannel);
2364 try {
2365 ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
2366 reader.go();
2367 } finally {
2368 Binder.defaultBlocking(mReceiveChannel);
2369 }
2370 }
2371
Dianne Hackborn16036f22015-06-22 14:05:51 -07002372 /** @hide */
2373 public void ensureData() {
2374 if (mHaveData) {
2375 return;
2376 }
2377 mHaveData = true;
Dianne Hackborn782d4982015-07-08 17:36:37 -07002378 ParcelTransferReader reader = new ParcelTransferReader(mReceiveChannel);
2379 reader.go();
Dianne Hackborn16036f22015-06-22 14:05:51 -07002380 }
2381
Dianne Hackborn782d4982015-07-08 17:36:37 -07002382 boolean waitForReady() {
Dianne Hackborn16036f22015-06-22 14:05:51 -07002383 boolean skipStructure = false;
2384 synchronized (this) {
2385 long endTime = SystemClock.uptimeMillis() + 5000;
2386 long now;
2387 while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) {
2388 try {
2389 wait(endTime-now);
2390 } catch (InterruptedException e) {
2391 }
2392 }
2393 if (mPendingAsyncChildren.size() > 0) {
2394 // We waited too long, assume none of the assist structure is valid.
Dianne Hackborn70d8be72015-06-23 19:33:02 +00002395 Log.w(TAG, "Skipping assist structure, waiting too long for async children (have "
2396 + mPendingAsyncChildren.size() + " remaining");
Dianne Hackborn16036f22015-06-22 14:05:51 -07002397 skipStructure = true;
2398 }
2399 }
Dianne Hackborn782d4982015-07-08 17:36:37 -07002400 return !skipStructure;
Dianne Hackborn16036f22015-06-22 14:05:51 -07002401 }
2402
Dianne Hackborn782d4982015-07-08 17:36:37 -07002403 /** @hide */
2404 public void clearSendChannel() {
2405 if (mSendChannel != null) {
2406 mSendChannel.mAssistStructure = null;
Dianne Hackborn16036f22015-06-22 14:05:51 -07002407 }
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002408 }
2409
Felipe Leme0200d9e2017-01-24 15:10:26 -08002410 @Override
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002411 public int describeContents() {
2412 return 0;
2413 }
2414
Felipe Leme0200d9e2017-01-24 15:10:26 -08002415 @Override
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002416 public void writeToParcel(Parcel out, int flags) {
Winson Chung48b25652018-10-22 14:04:30 -07002417 out.writeInt(mTaskId);
2418 ComponentName.writeToParcel(mActivityComponent, out);
Amith Yamasani858f98d2017-02-22 12:59:53 -08002419 out.writeInt(mIsHomeActivity ? 1 : 0);
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002420 if (mHaveData) {
2421 // This object holds its data. We want to write a send channel that the
2422 // other side can use to retrieve that data.
2423 if (mSendChannel == null) {
Dianne Hackborn782d4982015-07-08 17:36:37 -07002424 mSendChannel = new SendChannel(this);
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002425 }
2426 out.writeStrongBinder(mSendChannel);
2427 } else {
2428 // This object doesn't hold its data, so just propagate along its receive channel.
2429 out.writeStrongBinder(mReceiveChannel);
2430 }
2431 }
2432
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07002433 public static final @android.annotation.NonNull Parcelable.Creator<AssistStructure> CREATOR
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002434 = new Parcelable.Creator<AssistStructure>() {
Felipe Leme0200d9e2017-01-24 15:10:26 -08002435 @Override
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002436 public AssistStructure createFromParcel(Parcel in) {
2437 return new AssistStructure(in);
2438 }
2439
Felipe Leme0200d9e2017-01-24 15:10:26 -08002440 @Override
Dianne Hackborn69c6adc2015-06-02 10:52:59 -07002441 public AssistStructure[] newArray(int size) {
2442 return new AssistStructure[size];
2443 }
2444 };
2445}