package android.app.assist; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.graphics.Matrix; import android.graphics.Rect; import android.net.Uri; import android.os.BadParcelableException; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; import android.os.PooledStringReader; import android.os.PooledStringWriter; import android.os.RemoteException; import android.os.SystemClock; import android.service.autofill.FillRequest; import android.text.Spanned; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.view.View; import android.view.View.AutofillImportance; import android.view.ViewRootImpl; import android.view.ViewStructure; import android.view.ViewStructure.HtmlInfo; import android.view.ViewStructure.HtmlInfo.Builder; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; /** *
This API automatically creates assist data from the platform's * implementation of assist and autofill. * *
The structure is used for assist purposes when created by * {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)}, * or {@link View#onProvideVirtualStructure(ViewStructure)}. * *
The structure is also used for autofill purposes when created by * {@link View#onProvideAutofillStructure(ViewStructure, int)}, * or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}. * *
For performance reasons, some properties of the assist data might only be available for * assist or autofill purposes. In those cases, a property's availability will be documented * in its javadoc. * *
To learn about using Autofill in your app, read the
* Autofill Framework guides.
*/
public class AssistStructure implements Parcelable {
private static final String TAG = "AssistStructure";
private static final boolean DEBUG_PARCEL = false;
private static final boolean DEBUG_PARCEL_CHILDREN = false;
private static final boolean DEBUG_PARCEL_TREE = false;
private static final int VALIDATE_WINDOW_TOKEN = 0x11111111;
private static final int VALIDATE_VIEW_TOKEN = 0x22222222;
private boolean mHaveData;
// The task id and component of the activity which this assist structure is for
private int mTaskId;
private ComponentName mActivityComponent;
private boolean mIsHomeActivity;
private int mFlags;
private int mAutofillFlags;
private final ArrayList It's only relevant when the {@link AssistStructure} is used for autofill purposes.
*
* @return id that can be used to autofill the view contents, or {@code null} if the
* structure was created for assist purposes.
*/
@Nullable public AutofillId getAutofillId() {
return mAutofillId;
}
/**
* Gets the type of value that can be used to autofill the view contents.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes.
*
* @return autofill type as defined by {@link View#getAutofillType()},
* or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for assist purposes.
*/
public @View.AutofillType int getAutofillType() {
return mAutofillType;
}
/**
* Describes the content of a view so that a autofill service can fill in the appropriate
* data.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for Assist - see {@link View#getAutofillHints()} for more info.
*
* @return The autofill hints for this view, or {@code null} if the structure was created
* for assist purposes.
*/
@Nullable public String[] getAutofillHints() {
return mAutofillHints;
}
/**
* Gets the value of this view.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for assist purposes.
*
* @return the autofill value of this view, or {@code null} if the structure was created
* for assist purposes.
*/
@Nullable public AutofillValue getAutofillValue() {
return mAutofillValue;
}
/** @hide **/
public void setAutofillOverlay(AutofillOverlay overlay) {
mAutofillOverlay = overlay;
}
/**
* Gets the options that can be used to autofill this view.
*
* Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate
* the meaning of each possible value in the list.
*
* It's relevant when the {@link AssistStructure} is used for autofill purposes, not
* for assist purposes.
*
* @return the options that can be used to autofill this view, or {@code null} if the
* structure was created for assist purposes.
*/
@Nullable public CharSequence[] getAutofillOptions() {
return mAutofillOptions;
}
/**
* Gets the {@link android.text.InputType} bits of this structure.
*
* @return bits as defined by {@link android.text.InputType}.
*/
public int getInputType() {
return mInputType;
}
/** @hide */
public boolean isSanitized() {
return mSanitized;
}
/**
* Updates the {@link AutofillValue} of this structure.
*
* Should be used just before sending the structure to the
* {@link android.service.autofill.AutofillService} for saving, since it will override the
* initial value.
*
* @hide
*/
public void updateAutofillValue(AutofillValue value) {
mAutofillValue = value;
if (value.isText()) {
if (mText == null) {
mText = new ViewNodeText();
}
mText.mText = value.getTextValue();
}
}
/**
* Returns the left edge of this view, in pixels, relative to the left edge of its parent.
*/
public int getLeft() {
return mX;
}
/**
* Returns the top edge of this view, in pixels, relative to the top edge of its parent.
*/
public int getTop() {
return mY;
}
/**
* Returns the current X scroll offset of this view, as per
* {@link android.view.View#getScrollX() View.getScrollX()}.
*/
public int getScrollX() {
return mScrollX;
}
/**
* Returns the current Y scroll offset of this view, as per
* {@link android.view.View#getScrollX() View.getScrollY()}.
*/
public int getScrollY() {
return mScrollY;
}
/**
* Returns the width of this view, in pixels.
*/
public int getWidth() {
return mWidth;
}
/**
* Returns the height of this view, in pixels.
*/
public int getHeight() {
return mHeight;
}
/**
* Returns the transformation that has been applied to this view, such as a translation
* or scaling. The returned Matrix object is owned by ViewNode; do not modify it.
* Returns null if there is no transformation applied to the view.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public Matrix getTransformation() {
return mMatrix;
}
/**
* Returns the visual elevation of the view, used for shadowing and other visual
* characterstics, as set by {@link ViewStructure#setElevation
* ViewStructure.setElevation(float)}.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public float getElevation() {
return mElevation;
}
/**
* Returns the alpha transformation of the view, used to reduce the overall opacity
* of the view's contents, as set by {@link ViewStructure#setAlpha
* ViewStructure.setAlpha(float)}.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public float getAlpha() {
return mAlpha;
}
/**
* Returns the visibility mode of this view, as per
* {@link android.view.View#getVisibility() View.getVisibility()}.
*/
public int getVisibility() {
return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
}
/**
* Returns true if assist data has been blocked starting at this node in the hierarchy.
*/
public boolean isAssistBlocked() {
return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) != 0;
}
/**
* Returns true if this node is in an enabled state.
*/
public boolean isEnabled() {
return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
}
/**
* Returns true if this node is clickable by the user.
*/
public boolean isClickable() {
return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
}
/**
* Returns true if this node can take input focus.
*/
public boolean isFocusable() {
return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
}
/**
* Returns true if this node currently had input focus at the time that the
* structure was collected.
*/
public boolean isFocused() {
return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
}
/**
* Returns true if this node currently had accessibility focus at the time that the
* structure was collected.
*/
public boolean isAccessibilityFocused() {
return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
}
/**
* Returns true if this node represents something that is checkable by the user.
*/
public boolean isCheckable() {
return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
}
/**
* Returns true if this node is currently in a checked state.
*/
public boolean isChecked() {
return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
}
/**
* Returns true if this node has currently been selected by the user.
*/
public boolean isSelected() {
return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
}
/**
* Returns true if this node has currently been activated by the user.
*/
public boolean isActivated() {
return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
}
/**
* Returns true if this node is opaque.
*/
public boolean isOpaque() { return (mFlags&ViewNode.FLAGS_OPAQUE) != 0; }
/**
* Returns true if this node is something the user can perform a long click/press on.
*/
public boolean isLongClickable() {
return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
}
/**
* Returns true if this node is something the user can perform a context click on.
*/
public boolean isContextClickable() {
return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
}
/**
* Returns the class name of the node's implementation, indicating its behavior.
* For example, a button will report "android.widget.Button" meaning it behaves
* like a {@link android.widget.Button}.
*/
@Nullable
public String getClassName() {
return mClassName;
}
/**
* Returns any content description associated with the node, which semantically describes
* its purpose for accessibility and other uses.
*/
@Nullable
public CharSequence getContentDescription() {
return mContentDescription;
}
/**
* Returns the domain of the HTML document represented by this view.
*
* Typically used when the view associated with the view is a container for an HTML
* document.
*
* Warning: an autofill service cannot trust the value reported by this method
* without verifing its authenticity—see the "Web security" section of
* {@link android.service.autofill.AutofillService} for more details.
*
* @return domain-only part of the document. For example, if the full URL is
* {@code https://example.com/login?user=my_user}, it returns {@code example.com}.
*/
@Nullable public String getWebDomain() {
return mWebDomain;
}
/**
* @hide
*/
public void setWebDomain(@Nullable String domain) {
if (domain == null) return;
Uri uri = Uri.parse(domain);
if (uri == null) {
// Cannot log domain because it could contain PII;
Log.w(TAG, "Failed to parse web domain");
return;
}
mWebScheme = uri.getScheme();
if (mWebScheme == null) {
uri = Uri.parse("http://" + domain);
}
mWebDomain = uri.getHost();
}
/**
* Returns the scheme of the HTML document represented by this view.
*
* Typically used when the view associated with the view is a container for an HTML
* document.
*
* @return scheme-only part of the document. For example, if the full URL is
* {@code https://example.com/login?user=my_user}, it returns {@code https}.
*/
@Nullable public String getWebScheme() {
return mWebScheme;
}
/**
* Returns the HTML properties associated with this view.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for assist purposes.
*
* @return the HTML properties associated with this view, or {@code null} if the
* structure was created for assist purposes.
*/
@Nullable public HtmlInfo getHtmlInfo() {
return mHtmlInfo;
}
/**
* Returns the list of locales associated with this view.
*/
@Nullable public LocaleList getLocaleList() {
return mLocaleList;
}
/**
* Returns the MIME types accepted by {@link View#performReceiveContent} for this view. See
* {@link View#getReceiveContentMimeTypes()} for details.
*/
@Nullable
@SuppressLint("NullableCollection")
public String[] getReceiveContentMimeTypes() {
return mReceiveContentMimeTypes;
}
/**
* Returns any text associated with the node that is displayed to the user, or null
* if there is none.
*
* The text will be stripped of any spans that could potentially contain reference to
* the activity context, to avoid memory leak. If the text contained a span, a plain
* string version of the text will be returned.
*/
@Nullable
public CharSequence getText() {
return mText != null ? mText.mText : null;
}
/**
* If {@link #getText()} is non-null, this is where the current selection starts.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public int getTextSelectionStart() {
return mText != null ? mText.mTextSelectionStart : -1;
}
/**
* If {@link #getText()} is non-null, this is where the current selection starts.
* If there is no selection, returns the same value as {@link #getTextSelectionStart()},
* indicating the cursor position.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public int getTextSelectionEnd() {
return mText != null ? mText.mTextSelectionEnd : -1;
}
/**
* If {@link #getText()} is non-null, this is the main text color associated with it.
* If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
* Note that the text may also contain style spans that modify the color of specific
* parts of the text.
*/
public int getTextColor() {
return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
}
/**
* If {@link #getText()} is non-null, this is the main text background color associated
* with it.
* If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
* Note that the text may also contain style spans that modify the color of specific
* parts of the text.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public int getTextBackgroundColor() {
return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
}
/**
* If {@link #getText()} is non-null, this is the main text size (in pixels) associated
* with it.
* Note that the text may also contain style spans that modify the size of specific
* parts of the text.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public float getTextSize() {
return mText != null ? mText.mTextSize : 0;
}
/**
* If {@link #getText()} is non-null, this is the main text style associated
* with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
* {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
* {@link #TEXT_STYLE_UNDERLINE}.
* Note that the text may also contain style spans that modify the style of specific
* parts of the text.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
public int getTextStyle() {
return mText != null ? mText.mTextStyle : 0;
}
/**
* Return per-line offsets into the text returned by {@link #getText()}. Each entry
* in the array is a formatted line of text, and the value it contains is the offset
* into the text string where that line starts. May return null if there is no line
* information.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
@Nullable
public int[] getTextLineCharOffsets() {
return mText != null ? mText.mLineCharOffsets : null;
}
/**
* Return per-line baselines into the text returned by {@link #getText()}. Each entry
* in the array is a formatted line of text, and the value it contains is the baseline
* where that text appears in the view. May return null if there is no line
* information.
*
* It's only relevant when the {@link AssistStructure} is used for assist purposes,
* not for autofill purposes.
*/
@Nullable
public int[] getTextLineBaselines() {
return mText != null ? mText.mLineBaselines : null;
}
/**
* Gets the identifier used to set the text associated with this view.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for assist purposes.
*/
@Nullable
public String getTextIdEntry() {
return mTextIdEntry;
}
/**
* Return additional hint text associated with the node; this is typically used with
* a node that takes user input, describing to the user what the input means.
*/
@Nullable
public String getHint() {
return mText != null ? mText.mHint : null;
}
/**
* Gets the identifier used to set the hint associated with this view.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for assist purposes.
*/
@Nullable
public String getHintIdEntry() {
return mHintIdEntry;
}
/**
* Return a Bundle containing optional vendor-specific extension information.
*/
@Nullable
public Bundle getExtras() {
return mExtras;
}
/**
* Return the number of children this node has.
*/
public int getChildCount() {
return mChildren != null ? mChildren.length : 0;
}
/**
* Return a child of this node, given an index value from 0 to
* {@link #getChildCount()}-1.
*/
public ViewNode getChildAt(int index) {
return mChildren[index];
}
/**
* Returns the minimum width in ems of the text associated with this node, or {@code -1}
* if not supported by the node.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for assist purposes.
*/
public int getMinTextEms() {
return mMinEms;
}
/**
* Returns the maximum width in ems of the text associated with this node, or {@code -1}
* if not supported by the node.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for assist purposes.
*/
public int getMaxTextEms() {
return mMaxEms;
}
/**
* Returns the maximum length of the text associated with this node, or {@code -1} if not
* supported by the node or not set. System may set a default value if the text length is
* not set.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes,
* not for assist purposes.
*/
public int getMaxTextLength() {
return mMaxLength;
}
/**
* Gets the {@link View#setImportantForAutofill(int) importantForAutofill mode} of
* the view associated with this node.
*
* It's only relevant when the {@link AssistStructure} is used for autofill purposes.
*/
public @AutofillImportance int getImportantForAutofill() {
return mImportantForAutofill;
}
}
/**
* A parcelable wrapper class around {@link ViewNode}.
*
* This class, when parceled and unparceled, does not carry the child nodes.
*
* @hide
*/
public static final class ViewNodeParcelable implements Parcelable {
@NonNull
private final ViewNode mViewNode;
public ViewNodeParcelable(@NonNull ViewNode viewNode) {
mViewNode = viewNode;
}
public ViewNodeParcelable(@NonNull Parcel in) {
mViewNode = new ViewNode(in);
}
@NonNull
public ViewNode getViewNode() {
return mViewNode;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
mViewNode.writeSelfToParcel(parcel, /*pwriter=*/null, /*sanitizeOnWrite=*/false,
/*tmpMatrix*/null, /*willWriteChildren=*/ false);
}
@NonNull
public static final Parcelable.Creator