diff options
| author | Nikita Dubrovsky <dubrovsky@google.com> | 2020-09-09 15:45:38 -0700 |
|---|---|---|
| committer | Nikita Dubrovsky <dubrovsky@google.com> | 2021-01-11 20:57:48 +0000 |
| commit | e8f7c4ba7c7a39c7294eed0a37e9b69ca93310f6 (patch) | |
| tree | 916c0d4fd3d73266805ee3cf31debc2e9a12178c /core/java/android | |
| parent | 677c97ddf8cf663c73673b9f454fbedd726e3150 (diff) | |
Add MIME types to ViewStructure and autofill/cc ViewNode classes
Bug: 168253885
Test: atest FrameworksCoreTests:TextViewOnReceiveContentTest
Test: Manual
CTS-Coverage-Bug: 170893906
Change-Id: Iac8f73a7a022f20f59ecef9be89e3189ca106e4c
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/assist/AssistStructure.java | 29 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 1 | ||||
| -rw-r--r-- | core/java/android/view/ViewStructure.java | 8 | ||||
| -rw-r--r-- | core/java/android/view/contentcapture/ViewNode.java | 22 | ||||
| -rw-r--r-- | core/java/android/widget/Editor.java | 15 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 12 | ||||
| -rw-r--r-- | core/java/android/widget/TextViewOnReceiveContentListener.java | 15 |
7 files changed, 96 insertions, 6 deletions
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 0f7fac4eefa5..65a21640bb98 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -672,6 +672,7 @@ public class AssistStructure implements Parcelable { static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000; static final int FLAGS_OPAQUE = 0x00008000; + static final int FLAGS_HAS_MIME_TYPES = 0x80000000; static final int FLAGS_HAS_MATRIX = 0x40000000; static final int FLAGS_HAS_ALPHA = 0x20000000; static final int FLAGS_HAS_ELEVATION = 0x10000000; @@ -715,6 +716,7 @@ public class AssistStructure implements Parcelable { String mWebDomain; Bundle mExtras; LocaleList mLocaleList; + String[] mOnReceiveContentMimeTypes; ViewNode[] mChildren; @@ -880,6 +882,9 @@ public class AssistStructure implements Parcelable { if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) { mLocaleList = in.readParcelable(null); } + if ((flags & FLAGS_HAS_MIME_TYPES) != 0) { + mOnReceiveContentMimeTypes = in.readStringArray(); + } if ((flags&FLAGS_HAS_EXTRAS) != 0) { mExtras = in.readBundle(); } @@ -939,6 +944,9 @@ public class AssistStructure implements Parcelable { if (mLocaleList != null) { flags |= FLAGS_HAS_LOCALE_LIST; } + if (mOnReceiveContentMimeTypes != null) { + flags |= FLAGS_HAS_MIME_TYPES; + } if (mExtras != null) { flags |= FLAGS_HAS_EXTRAS; } @@ -1109,6 +1117,9 @@ public class AssistStructure implements Parcelable { if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) { out.writeParcelable(mLocaleList, 0); } + if ((flags & FLAGS_HAS_MIME_TYPES) != 0) { + out.writeStringArray(mOnReceiveContentMimeTypes); + } if ((flags&FLAGS_HAS_EXTRAS) != 0) { out.writeBundle(mExtras); } @@ -1527,6 +1538,15 @@ public class AssistStructure implements Parcelable { } /** + * Returns the MIME types accepted by {@link View#performReceiveContent} for this view. See + * {@link View#getOnReceiveContentMimeTypes()} for details. + */ + @Nullable + public String[] getOnReceiveContentMimeTypes() { + return mOnReceiveContentMimeTypes; + } + + /** * Returns any text associated with the node that is displayed to the user, or null * if there is none. */ @@ -2146,6 +2166,11 @@ public class AssistStructure implements Parcelable { } @Override + public void setOnReceiveContentMimeTypes(@Nullable String[] mimeTypes) { + mNode.mOnReceiveContentMimeTypes = mimeTypes; + } + + @Override public void setInputType(int inputType) { mNode.mInputType = inputType; } @@ -2422,6 +2447,10 @@ public class AssistStructure implements Parcelable { if (localeList != null) { Log.i(TAG, prefix + " LocaleList: " + localeList); } + String[] mimeTypes = node.getOnReceiveContentMimeTypes(); + if (mimeTypes != null) { + Log.i(TAG, prefix + " MIME types: " + Arrays.toString(mimeTypes)); + } String hint = node.getHint(); if (hint != null) { Log.i(TAG, prefix + " Hint: " + hint); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 0f5321548f95..e8584dac90c8 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8821,6 +8821,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, structure.setAutofillValue(getAutofillValue()); } structure.setImportantForAutofill(getImportantForAutofill()); + structure.setOnReceiveContentMimeTypes(getOnReceiveContentMimeTypes()); } int ignoredParentLeft = 0; diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index 29ce231d5d87..f5aa97a88608 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -372,6 +372,14 @@ public abstract class ViewStructure { public void setImportantForAutofill(@AutofillImportance int mode) {} /** + * Sets the MIME types accepted by this view. See {@link View#getOnReceiveContentMimeTypes()}. + * + * <p>Should only be set when the node is used for Autofill or Content Capture purposes - it + * will be ignored when used for Assist. + */ + public void setOnReceiveContentMimeTypes(@Nullable String[] mimeTypes) {} + + /** * Sets the {@link android.text.InputType} bits of this node. * * @param inputType inputType bits as defined by {@link android.text.InputType}. diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java index e731d4b76fb9..4e9c229e03a0 100644 --- a/core/java/android/view/contentcapture/ViewNode.java +++ b/core/java/android/view/contentcapture/ViewNode.java @@ -81,6 +81,7 @@ public final class ViewNode extends AssistStructure.ViewNode { private static final long FLAGS_HAS_AUTOFILL_HINTS = 1L << 33; private static final long FLAGS_HAS_AUTOFILL_OPTIONS = 1L << 34; private static final long FLAGS_HAS_HINT_ID_ENTRY = 1L << 35; + private static final long FLAGS_HAS_MIME_TYPES = 1L << 36; /** Flags used to optimize what's written to the parcel */ private long mFlags; @@ -113,6 +114,7 @@ public final class ViewNode extends AssistStructure.ViewNode { private String[] mAutofillHints; private AutofillValue mAutofillValue; private CharSequence[] mAutofillOptions; + private String[] mOnReceiveContentMimeTypes; /** @hide */ public ViewNode() { @@ -169,6 +171,9 @@ public final class ViewNode extends AssistStructure.ViewNode { if ((nodeFlags & FLAGS_HAS_LOCALE_LIST) != 0) { mLocaleList = parcel.readParcelable(null); } + if ((nodeFlags & FLAGS_HAS_MIME_TYPES) != 0) { + mOnReceiveContentMimeTypes = parcel.readStringArray(); + } if ((nodeFlags & FLAGS_HAS_INPUT_TYPE) != 0) { mInputType = parcel.readInt(); } @@ -463,6 +468,12 @@ public final class ViewNode extends AssistStructure.ViewNode { return mAutofillOptions; } + @Override + @Nullable + public String[] getOnReceiveContentMimeTypes() { + return mOnReceiveContentMimeTypes; + } + @Nullable @Override public LocaleList getLocaleList() { @@ -508,6 +519,9 @@ public final class ViewNode extends AssistStructure.ViewNode { if (mLocaleList != null) { nodeFlags |= FLAGS_HAS_LOCALE_LIST; } + if (mOnReceiveContentMimeTypes != null) { + nodeFlags |= FLAGS_HAS_MIME_TYPES; + } if (mInputType != 0) { nodeFlags |= FLAGS_HAS_INPUT_TYPE; } @@ -584,6 +598,9 @@ public final class ViewNode extends AssistStructure.ViewNode { if ((nodeFlags & FLAGS_HAS_LOCALE_LIST) != 0) { parcel.writeParcelable(mLocaleList, 0); } + if ((nodeFlags & FLAGS_HAS_MIME_TYPES) != 0) { + parcel.writeStringArray(mOnReceiveContentMimeTypes); + } if ((nodeFlags & FLAGS_HAS_INPUT_TYPE) != 0) { parcel.writeInt(mInputType); } @@ -912,6 +929,11 @@ public final class ViewNode extends AssistStructure.ViewNode { } @Override + public void setOnReceiveContentMimeTypes(@Nullable String[] mimeTypes) { + mNode.mOnReceiveContentMimeTypes = mimeTypes; + } + + @Override public void setAutofillHints(String[] hints) { mNode.mAutofillHints = hints; } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 0025d1e2a853..9ffb4bfbb9c1 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -99,6 +99,7 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; +import android.view.OnReceiveContentListener; import android.view.SubMenu; import android.view.View; import android.view.View.DragShadowBuilder; @@ -588,8 +589,18 @@ public class Editor { mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this); } - @VisibleForTesting - public @NonNull TextViewOnReceiveContentListener getDefaultOnReceiveContentListener() { + /** + * Returns the default handler for receiving content in an editable {@link TextView}. This + * listener impl is used to encapsulate the default behavior but it is not part of the public + * API. If an app wants to execute the default platform behavior for receiving content, it + * should call {@link View#onReceiveContent}. Alternatively, if an app implements a custom + * listener for receiving content and wants to delegate some of the content to be handled by + * the platform, it should return the corresponding content from its listener. See + * {@link View#setOnReceiveContentListener} and {@link OnReceiveContentListener} for more info. + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + @NonNull + public TextViewOnReceiveContentListener getDefaultOnReceiveContentListener() { return mDefaultOnReceiveContentListener; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 4edfc5f309b2..2a21c3aa2e57 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -11686,6 +11686,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } } + String[] mimeTypes = getOnReceiveContentMimeTypes(); + if (mimeTypes == null && mEditor != null) { + // If the app hasn't set a listener for receiving content on this view (ie, + // getOnReceiveContentMimeTypes() returns null), check if it implements the + // keyboard image API and, if possible, use those MIME types as fallback. + // This fallback is only in place for autofill, not other mechanisms for + // inserting content. See AUTOFILL_NON_TEXT_REQUIRES_ON_RECEIVE_CONTENT_LISTENER + // in TextViewOnReceiveContentListener for more info. + mimeTypes = mEditor.getDefaultOnReceiveContentListener() + .getFallbackMimeTypesForAutofill(this); + } + structure.setOnReceiveContentMimeTypes(mimeTypes); } if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL diff --git a/core/java/android/widget/TextViewOnReceiveContentListener.java b/core/java/android/widget/TextViewOnReceiveContentListener.java index 8cef1061c423..91fac5511807 100644 --- a/core/java/android/widget/TextViewOnReceiveContentListener.java +++ b/core/java/android/widget/TextViewOnReceiveContentListener.java @@ -60,7 +60,7 @@ import java.util.Arrays; * * @hide */ -@VisibleForTesting +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public final class TextViewOnReceiveContentListener implements OnReceiveContentListener { private static final String LOG_TAG = "ReceiveContent"; @@ -261,10 +261,17 @@ public final class TextViewOnReceiveContentListener implements OnReceiveContentL mInputConnectionInfo = null; } - /** @hide */ - @VisibleForTesting + /** + * Returns the MIME types accepted by {@link View#performReceiveContent} for the given view, + * <strong>for autofill purposes</strong>. This will be non-null only if fallback to the + * keyboard image API {@link #isUsageOfImeCommitContentEnabled is enabled} and the view has an + * {@link InputConnection} with {@link EditorInfo#contentMimeTypes} populated. + * + * @hide + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) @Nullable - public String[] getEditorInfoMimeTypes(@NonNull TextView view) { + public String[] getFallbackMimeTypesForAutofill(@NonNull TextView view) { if (!isUsageOfImeCommitContentEnabled(view)) { return null; } |
