diff options
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | api/system-current.txt | 2 | ||||
| -rw-r--r-- | api/test-current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/app/assist/AssistStructure.java | 21 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 8 | ||||
| -rw-r--r-- | core/java/android/view/ViewStructure.java | 9 | ||||
| -rw-r--r-- | core/java/android/view/autofill/AutoFillType.java | 2 | ||||
| -rw-r--r-- | core/java/android/widget/AdapterView.java | 6 | ||||
| -rw-r--r-- | core/java/android/widget/RadioGroup.java | 11 | ||||
| -rw-r--r-- | core/java/android/widget/Spinner.java | 40 |
10 files changed, 98 insertions, 5 deletions
diff --git a/api/current.txt b/api/current.txt index 61ddd76f5282..04cdf0523d26 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6547,6 +6547,7 @@ package android.app.assist { public static class AssistStructure.ViewNode { method public float getAlpha(); method public android.view.autofill.AutoFillId getAutoFillId(); + method public java.lang.String[] getAutoFillOptions(); method public android.view.autofill.AutoFillType getAutoFillType(); method public android.view.autofill.AutoFillValue getAutoFillValue(); method public android.app.assist.AssistStructure.ViewNode getChildAt(int); @@ -45644,6 +45645,7 @@ package android.view { method public abstract void setAccessibilityFocused(boolean); method public abstract void setActivated(boolean); method public abstract void setAlpha(float); + method public abstract void setAutoFillOptions(java.lang.String[]); method public abstract void setAutoFillType(android.view.autofill.AutoFillType); method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue); method public abstract void setCheckable(boolean); diff --git a/api/system-current.txt b/api/system-current.txt index e170345faa4f..0aa629670ad7 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6787,6 +6787,7 @@ package android.app.assist { public static class AssistStructure.ViewNode { method public float getAlpha(); method public android.view.autofill.AutoFillId getAutoFillId(); + method public java.lang.String[] getAutoFillOptions(); method public android.view.autofill.AutoFillType getAutoFillType(); method public android.view.autofill.AutoFillValue getAutoFillValue(); method public android.app.assist.AssistStructure.ViewNode getChildAt(int); @@ -49189,6 +49190,7 @@ package android.view { method public abstract void setAccessibilityFocused(boolean); method public abstract void setActivated(boolean); method public abstract void setAlpha(float); + method public abstract void setAutoFillOptions(java.lang.String[]); method public abstract void setAutoFillType(android.view.autofill.AutoFillType); method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue); method public abstract void setCheckable(boolean); diff --git a/api/test-current.txt b/api/test-current.txt index af51baafc1b3..22dcb7026bfe 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -6573,6 +6573,7 @@ package android.app.assist { public static class AssistStructure.ViewNode { method public float getAlpha(); method public android.view.autofill.AutoFillId getAutoFillId(); + method public java.lang.String[] getAutoFillOptions(); method public android.view.autofill.AutoFillType getAutoFillType(); method public android.view.autofill.AutoFillValue getAutoFillValue(); method public android.app.assist.AssistStructure.ViewNode getChildAt(int); @@ -46006,6 +46007,7 @@ package android.view { method public abstract void setAccessibilityFocused(boolean); method public abstract void setActivated(boolean); method public abstract void setAlpha(float); + method public abstract void setAutoFillOptions(java.lang.String[]); method public abstract void setAutoFillType(android.view.autofill.AutoFillType); method public abstract void setAutoFillValue(android.view.autofill.AutoFillValue); method public abstract void setCheckable(boolean); diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 678c017febe0..716bbe9458c0 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -538,6 +538,7 @@ public class AssistStructure implements Parcelable { AutoFillId mAutoFillId; AutoFillType mAutoFillType; AutoFillValue mAutoFillValue; + String[] mAutoFillOptions; boolean mSanitized; int mX; int mY; @@ -618,6 +619,7 @@ public class AssistStructure implements Parcelable { mAutoFillId = in.readParcelable(null); mAutoFillType = in.readParcelable(null); mAutoFillValue = in.readParcelable(null); + mAutoFillOptions = in.readStringArray(); } if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) { mX = in.readInt(); @@ -738,6 +740,7 @@ public class AssistStructure implements Parcelable { out.writeParcelable(mAutoFillType, 0); final AutoFillValue sanitizedValue = writeSensitive ? mAutoFillValue : null; out.writeParcelable(sanitizedValue, 0); + out.writeStringArray(mAutoFillOptions); } if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) { out.writeInt(mX); @@ -844,6 +847,19 @@ public class AssistStructure implements Parcelable { return mAutoFillValue; } + /** + * Gets the options that can be used to auto-fill this structure. + * + * <p>Typically used by nodes whose {@link AutoFillType} is a list to indicate the meaning + * of each possible value in the list. + * + * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not + * for assist. + */ + public String[] getAutoFillOptions() { + return mAutoFillOptions; + } + /** @hide */ public boolean isSanitized() { return mSanitized; @@ -1506,6 +1522,11 @@ public class AssistStructure implements Parcelable { mNode.mAutoFillValue = value; } + @Override + public void setAutoFillOptions(String[] options) { + mNode.mAutoFillOptions = options; + } + /** * @hide */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index e7838a7521e0..86669308539a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6993,8 +6993,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Called when assist structure is being retrieved from a view as part of an auto-fill request. * * <p>This method already provides most of what's needed for auto-fill, but should be overridden - * when the view contents does not include PII (Personally Identifiable Information) (so it - * can call {@link ViewStructure#setSanitized(boolean) ViewStructure#setSanitized(true)}). + * <ol> + * <li>The view contents does not include PII (Personally Identifiable Information), so it + * can call {@link ViewStructure#setSanitized(boolean)} passing {@code true}. + * <li>It must set fields such {@link ViewStructure#setText(CharSequence)}, + * {@link ViewStructure#setAutoFillOptions(String[])}, or {@link ViewStructure#setUrl(String)}. + * </ol> * * @param structure Fill in with structured view data. The default implementation * fills in all data that can be inferred from the view itself. diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index bc2725f56bf6..84c2c8452e98 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -307,6 +307,15 @@ public abstract class ViewStructure { public abstract void setAutoFillValue(AutoFillValue value); /** + * Sets the options that can be used to auto-fill this node. + * + * <p>Typically used by nodes whose {@link AutoFillType} is a list to indicate the meaning of + * each possible value in the list. + */ + // TODO(b/33197203, b/33802548): add CTS/unit test + public abstract void setAutoFillOptions(String[] options); + + /** * Marks this node as sanitized so its content are sent on {@link * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure, * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)}. diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java index 017f7f8ca3e8..5d85bfdac095 100644 --- a/core/java/android/view/autofill/AutoFillType.java +++ b/core/java/android/view/autofill/AutoFillType.java @@ -44,8 +44,6 @@ public final class AutoFillType implements Parcelable { private static final int TYPE_TEXT = 1; private static final int TYPE_TOGGLE = 2; - // TODO(b/33197203): make sure it works with Spinners and/or add a new type for them - // (since they're often used for credit card selection) private static final int TYPE_LIST = 3; // TODO(b/33197203): add others, like date picker? That would be trick, because they're set as: diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index 2cfefba10c57..0b3cff10d17e 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -34,6 +34,7 @@ import android.view.ViewHierarchyEncoder; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.autofill.AutoFillManager; /** * An AdapterView is a view whose children are determined by an {@link Adapter}. @@ -914,6 +915,11 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { dispatchOnItemSelected(); } } + // Always notify AutoFillManager - it will return right away if auto-fill is disabled. + final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class); + if (afm != null) { + afm.valueChanged(this); + } } private void dispatchOnItemSelected() { diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java index 76b38131477d..49253eb609cf 100644 --- a/core/java/android/widget/RadioGroup.java +++ b/core/java/android/widget/RadioGroup.java @@ -430,6 +430,15 @@ public class RadioGroup extends LinearLayout { @Override public AutoFillValue getAutoFillValue() { - return isEnabled() ? AutoFillValue.forList(getCheckedRadioButtonId()) : null; + if (!isEnabled()) return null; + + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getId() == mCheckedId) { + return AutoFillValue.forList(i); + } + } + return null; } } diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index 28cc693f3b31..50c016bb4c3a 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -41,9 +41,12 @@ import android.view.MotionEvent; import android.view.PointerIcon; import android.view.View; import android.view.ViewGroup; +import android.view.ViewStructure; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.autofill.AutoFillType; +import android.view.autofill.AutoFillValue; import android.widget.PopupWindow.OnDismissListener; import com.android.internal.R; @@ -784,6 +787,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { return handled; } + @Override public void onClick(DialogInterface dialog, int which) { setSelection(which); dialog.dismiss(); @@ -912,6 +916,42 @@ public class Spinner extends AbsSpinner implements OnClickListener { return super.onResolvePointerIcon(event, pointerIndex); } + // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable) + + @Override + public void onProvideAutoFillStructure(ViewStructure structure, int flags) { + super.onProvideAutoFillStructure(structure, flags); + // TODO(b/33197203): implement sanitization so initial value is only sanitized when coming + // from resources. + + final int count = getAdapter().getCount(); + if (count > 0) { + final String[] options = new String[count]; + for (int i = 0; i < count; i++) { + options[i] = getAdapter().getItem(i).toString(); + } + structure.setAutoFillOptions(options); + } + } + + @Override + public void autoFill(AutoFillValue value) { + if (!isEnabled()) return; + + final int position = value.getListValue(); + setSelection(position); + } + + @Override + public AutoFillType getAutoFillType() { + return AutoFillType.forList(); + } + + @Override + public AutoFillValue getAutoFillValue() { + return isEnabled() ? AutoFillValue.forList(getSelectedItemPosition()) : null; + } + static class SavedState extends AbsSpinner.SavedState { boolean showDropdown; |