Loading core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -51432,6 +51432,7 @@ package android.view { method public boolean isAutoHandwritingEnabled(); method public boolean isClickable(); method public boolean isContextClickable(); method public boolean isCredential(); method public boolean isDirty(); method @Deprecated public boolean isDrawingCacheEnabled(); method public boolean isDuplicateParentStateEnabled(); Loading Loading @@ -51665,6 +51666,7 @@ package android.view { method public void setImportantForAccessibility(int); method public void setImportantForAutofill(int); method public void setImportantForContentCapture(int); method public void setIsCredential(boolean); method public void setKeepScreenOn(boolean); method public void setKeyboardNavigationCluster(boolean); method public void setLabelFor(@IdRes int); core/api/test-current.txt +8 −3 Original line number Diff line number Diff line Loading @@ -3206,6 +3206,14 @@ package android.view.animation { package android.view.autofill { public class AutofillFeatureFlags { field public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED = "autofill_credential_manager_enabled"; field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS = "autofill_credential_manager_ignore_views"; field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; } public final class AutofillId implements android.os.Parcelable { ctor public AutofillId(int); ctor public AutofillId(@NonNull android.view.autofill.AutofillId, int); Loading @@ -3217,9 +3225,6 @@ package android.view.autofill { } public final class AutofillManager { field public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0 field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1 field public static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 120000; // 0x1d4c0 Loading core/java/android/view/View.java +48 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ import android.view.accessibility.AccessibilityWindowInfo; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Transformation; import android.view.autofill.AutofillFeatureFlags; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; Loading Loading @@ -3662,6 +3663,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Indicates that the view enables auto handwriting initiation. */ private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000; /** * Indicates that the view is important for Credential Manager. */ private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000; /* End of masks for mPrivateFlags4 */ /** @hide */ Loading Loading @@ -6130,6 +6137,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setImportantForContentCapture(a.getInt(attr, IMPORTANT_FOR_CONTENT_CAPTURE_AUTO)); } break; case R.styleable.View_isCredential: if (a.peekValue(attr) != null) { setIsCredential(a.getBoolean(attr, false)); } break; case R.styleable.View_defaultFocusHighlightEnabled: if (a.peekValue(attr) != null) { setDefaultFocusHighlightEnabled(a.getBoolean(attr, true)); Loading Loading @@ -10234,6 +10247,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private boolean isAutofillable() { if (getAutofillType() == AUTOFILL_TYPE_NONE) return false; // Disable triggering autofill if the view is integrated with CredentialManager. if (AutofillFeatureFlags.shouldIgnoreCredentialViews() && isCredential()) return false; if (!isImportantForAutofill()) { // View is not important for "regular" autofill, so we must check if Augmented Autofill // is enabled for the activity Loading Loading @@ -31860,6 +31877,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } /** * Gets the mode for determining whether this view is a credential. * * <p>See {@link #isCredential()}. * * @param isCredential Whether the view is a credential. * * @attr ref android.R.styleable#View_isCredential */ public void setIsCredential(boolean isCredential) { if (isCredential) { mPrivateFlags4 |= PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER; } else { mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER; } } /** * Gets the mode for determining whether this view is a credential. * * <p>See {@link #setIsCredential(boolean)}. * * @return false by default, or value passed to {@link #setIsCredential(boolean)}. * * @attr ref android.R.styleable#View_isCredential */ public boolean isCredential() { return ((mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER) == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER); } /** * Set whether this view enables automatic handwriting initiation. * core/java/android/view/autofill/AutofillFeatureFlags.java 0 → 100644 +224 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.autofill; import android.annotation.TestApi; import android.provider.DeviceConfig; import android.text.TextUtils; import android.view.View; import com.android.internal.util.ArrayUtils; /** * Feature flags associated with autofill. * @hide */ @TestApi public class AutofillFeatureFlags { /** * {@code DeviceConfig} property used to set which Smart Suggestion modes for Augmented Autofill * are available. */ public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; /** * Sets how long (in ms) the augmented autofill service is bound while idle. * * <p>Use {@code 0} to keep it permanently bound. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT = "augmented_service_idle_unbind_timeout"; /** * Sets how long (in ms) the augmented autofill service request is killed if not replied. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT = "augmented_service_request_timeout"; /** * Sets allowed list for the autofill compatibility mode. * * The list of packages is {@code ":"} colon delimited, and each entry has the name of the * package and an optional list of url bar resource ids (the list is delimited by * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited). * * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 } * have 2 ids {@code url_foo} and {@code url_bas}) would be * {@code p1[url_bar]:p2:p3[url_foo,url_bas]} */ public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; /** * Indicates Fill dialog feature enabled or not. */ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; /** * Sets the autofill hints allowed list for the fields that can trigger the fill dialog * feature at Activity starting. * * The list of autofill hints is {@code ":"} colon delimited. * * <p>For example, a list with 3 hints {@code password}, {@code phone}, and * { @code emailAddress}, would be {@code password:phone:emailAddress} * * Note: By default the password field is enabled even there is no password hint in the list * * @see View#setAutofillHints(String...) * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS = "autofill_dialog_hints"; // START CREDENTIAL MANAGER FLAGS // /** * Indicates whether credential manager tagged views should be ignored from autofill structures. * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED} */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS = "autofill_credential_manager_ignore_views"; /** * Indicates CredentialManager feature enabled or not. * This is the overall feature flag. Individual behavior of credential manager may be controlled * via a different flag, but gated by this flag. */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED = "autofill_credential_manager_enabled"; /** * Indicates whether credential manager tagged views should suppress fill dialog. * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED} * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG = "autofill_credential_manager_suppress_fill_dialog"; /** * Indicates whether credential manager tagged views should suppress save dialog. * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED} * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_SAVE_DIALOG = "autofill_credential_manager_suppress_save_dialog"; // END CREDENTIAL MANAGER FLAGS // /** * Sets a value of delay time to show up the inline tooltip view. * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY = "autofill_inline_tooltip_first_show_delay"; private static final String DIALOG_HINTS_DELIMITER = ":"; private static final boolean DEFAULT_HAS_FILL_DIALOG_UI_FEATURE = false; private static final String DEFAULT_FILL_DIALOG_ENABLED_HINTS = ""; // CREDENTIAL MANAGER DEFAULTS // Credential manager is enabled by default so as to allow testing by app developers private static final boolean DEFAULT_CREDENTIAL_MANAGER_ENABLED = true; private static final boolean DEFAULT_CREDENTIAL_MANAGER_IGNORE_VIEWS = true; private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG = false; private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_SAVE_DIALOG = false; // END CREDENTIAL MANAGER DEFAULTS private AutofillFeatureFlags() {}; /** * Whether the fill dialog feature is enabled or not * * @hide */ public static boolean isFillDialogEnabled() { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED, DEFAULT_HAS_FILL_DIALOG_UI_FEATURE); } /** * Gets fill dialog enabled hints. * * @hide */ public static String[] getFillDialogEnabledHints() { final String dialogHints = DeviceConfig.getString( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS, DEFAULT_FILL_DIALOG_ENABLED_HINTS); if (TextUtils.isEmpty(dialogHints)) { return new String[0]; } return ArrayUtils.filter(dialogHints.split(DIALOG_HINTS_DELIMITER), String[]::new, (str) -> !TextUtils.isEmpty(str)); } /** * Whether the Credential Manager feature is enabled or not * * @hide */ public static boolean isCredentialManagerEnabled() { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED, DEFAULT_CREDENTIAL_MANAGER_ENABLED); } /** * Whether credential manager tagged views should be ignored for autofill structure. * * @hide */ public static boolean shouldIgnoreCredentialViews() { return isCredentialManagerEnabled() && DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS, DEFAULT_CREDENTIAL_MANAGER_IGNORE_VIEWS); } /** * Whether credential manager tagged views should not trigger fill dialog requests. * * @hide */ public static boolean isFillDialogDisabledForCredentialManager() { return isCredentialManagerEnabled() && DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG, DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG); } } core/java/android/view/autofill/AutofillManager.java +20 −109 Original line number Diff line number Diff line Loading @@ -60,7 +60,6 @@ import android.os.Looper; import android.os.Parcelable; import android.os.RemoteException; import android.os.SystemClock; import android.provider.DeviceConfig; import android.service.autofill.AutofillService; import android.service.autofill.FillCallback; import android.service.autofill.FillEventHistory; Loading Loading @@ -450,88 +449,6 @@ public final class AutofillManager { @Retention(RetentionPolicy.SOURCE) public @interface SmartSuggestionMode {} /** * {@code DeviceConfig} property used to set which Smart Suggestion modes for Augmented Autofill * are available. * * @hide */ @TestApi public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; /** * Sets how long (in ms) the augmented autofill service is bound while idle. * * <p>Use {@code 0} to keep it permanently bound. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT = "augmented_service_idle_unbind_timeout"; /** * Sets how long (in ms) the augmented autofill service request is killed if not replied. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT = "augmented_service_request_timeout"; /** * Sets allowed list for the autofill compatibility mode. * * The list of packages is {@code ":"} colon delimited, and each entry has the name of the * package and an optional list of url bar resource ids (the list is delimited by * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited). * * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 } * have 2 ids {@code url_foo} and {@code url_bas}) would be * {@code p1[url_bar]:p2:p3[url_foo,url_bas]} * * @hide */ @TestApi public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; /** * Sets the fill dialog feature enabled or not. * * @hide */ @TestApi public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; /** * Sets the autofill hints allowed list for the fields that can trigger the fill dialog * feature at Activity starting. * * The list of autofill hints is {@code ":"} colon delimited. * * <p>For example, a list with 3 hints {@code password}, {@code phone}, and * {@code emailAddress}, would be {@code password:phone:emailAddress} * * Note: By default the password field is enabled even there is no password hint in the list * * @see View#setAutofillHints(String...) * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS = "autofill_dialog_hints"; /** * Sets a value of delay time to show up the inline tooltip view. * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY = "autofill_inline_tooltip_first_show_delay"; private static final String DIALOG_HINTS_DELIMITER = ":"; /** @hide */ public static final int RESULT_OK = 0; /** @hide */ Loading Loading @@ -634,9 +551,6 @@ public final class AutofillManager { */ public static final int NO_SESSION = Integer.MAX_VALUE; private static final boolean HAS_FILL_DIALOG_UI_FEATURE_DEFAULT = false; private static final String FILL_DIALOG_ENABLED_DEFAULT_HINTS = ""; private final IAutoFillManager mService; private final Object mLock = new Object(); Loading Loading @@ -891,11 +805,8 @@ public final class AutofillManager { mOptions = context.getAutofillOptions(); mIsFillRequested = new AtomicBoolean(false); mIsFillDialogEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED, HAS_FILL_DIALOG_UI_FEATURE_DEFAULT); mFillDialogEnabledHints = getFillDialogEnabledHints(); mIsFillDialogEnabled = AutofillFeatureFlags.isFillDialogEnabled(); mFillDialogEnabledHints = AutofillFeatureFlags.getFillDialogEnabledHints(); if (sDebug) { Log.d(TAG, "Fill dialog is enabled:" + mIsFillDialogEnabled + ", hints=" + Arrays.toString(mFillDialogEnabledHints)); Loading @@ -907,19 +818,6 @@ public final class AutofillManager { } } private String[] getFillDialogEnabledHints() { final String dialogHints = DeviceConfig.getString( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS, FILL_DIALOG_ENABLED_DEFAULT_HINTS); if (TextUtils.isEmpty(dialogHints)) { return new String[0]; } return ArrayUtils.filter(dialogHints.split(DIALOG_HINTS_DELIMITER), String[]::new, (str) -> !TextUtils.isEmpty(str)); } /** * @hide */ Loading Loading @@ -1190,16 +1088,28 @@ public final class AutofillManager { } /** * The {@link #DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or the view have * the allowed autofill hints, performs a fill request to know there is any field supported * fill dialog. * The {@link AutofillFeatureFlags#DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or * the view have the allowed autofill hints, performs a fill request to know there is any field * supported fill dialog. * * @hide */ public void notifyViewEnteredForFillDialog(View v) { if (sDebug) { Log.d(TAG, "notifyViewEnteredForFillDialog:" + v.getAutofillId()); } if (!hasAutofillFeature()) { return; } if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager() && v.isCredential()) { if (sDebug) { Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:" + v.getAutofillId().toString()); } return; } synchronized (mLock) { if (mTrackedViews != null) { // To support the fill dialog can show for the autofillable Views in Loading Loading @@ -1227,8 +1137,8 @@ public final class AutofillManager { synchronized (mLock) { // To match the id of the IME served view, used AutofillId.NO_AUTOFILL_ID on prefill // request, because IME will reset the id of IME served view to 0 when activity // start and does not focus on any view. If the id of the prefill request is // not match to the IME served view's, Autofill will be blocking to wait inline // start and does not focus on any view. If the id of the prefill request does // not match the IME served view's, Autofill will be blocking to wait inline // request from the IME. notifyViewEnteredLocked(/* view= */ null, AutofillId.NO_AUTOFILL_ID, /* bounds= */ null, /* value= */ null, flags); Loading Loading @@ -4075,6 +3985,7 @@ public final class AutofillManager { } } @Override public void notifyFillDialogTriggerIds(List<AutofillId> ids) { final AutofillManager afm = mAfm.get(); if (afm != null) { Loading Loading
core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -51432,6 +51432,7 @@ package android.view { method public boolean isAutoHandwritingEnabled(); method public boolean isClickable(); method public boolean isContextClickable(); method public boolean isCredential(); method public boolean isDirty(); method @Deprecated public boolean isDrawingCacheEnabled(); method public boolean isDuplicateParentStateEnabled(); Loading Loading @@ -51665,6 +51666,7 @@ package android.view { method public void setImportantForAccessibility(int); method public void setImportantForAutofill(int); method public void setImportantForContentCapture(int); method public void setIsCredential(boolean); method public void setKeepScreenOn(boolean); method public void setKeyboardNavigationCluster(boolean); method public void setLabelFor(@IdRes int);
core/api/test-current.txt +8 −3 Original line number Diff line number Diff line Loading @@ -3206,6 +3206,14 @@ package android.view.animation { package android.view.autofill { public class AutofillFeatureFlags { field public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED = "autofill_credential_manager_enabled"; field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS = "autofill_credential_manager_ignore_views"; field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; } public final class AutofillId implements android.os.Parcelable { ctor public AutofillId(int); ctor public AutofillId(@NonNull android.view.autofill.AutofillId, int); Loading @@ -3217,9 +3225,6 @@ package android.view.autofill { } public final class AutofillManager { field public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0 field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1 field public static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 120000; // 0x1d4c0 Loading
core/java/android/view/View.java +48 −0 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ import android.view.accessibility.AccessibilityWindowInfo; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Transformation; import android.view.autofill.AutofillFeatureFlags; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; Loading Loading @@ -3662,6 +3663,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Indicates that the view enables auto handwriting initiation. */ private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000; /** * Indicates that the view is important for Credential Manager. */ private static final int PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER = 0x000020000; /* End of masks for mPrivateFlags4 */ /** @hide */ Loading Loading @@ -6130,6 +6137,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setImportantForContentCapture(a.getInt(attr, IMPORTANT_FOR_CONTENT_CAPTURE_AUTO)); } break; case R.styleable.View_isCredential: if (a.peekValue(attr) != null) { setIsCredential(a.getBoolean(attr, false)); } break; case R.styleable.View_defaultFocusHighlightEnabled: if (a.peekValue(attr) != null) { setDefaultFocusHighlightEnabled(a.getBoolean(attr, true)); Loading Loading @@ -10234,6 +10247,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private boolean isAutofillable() { if (getAutofillType() == AUTOFILL_TYPE_NONE) return false; // Disable triggering autofill if the view is integrated with CredentialManager. if (AutofillFeatureFlags.shouldIgnoreCredentialViews() && isCredential()) return false; if (!isImportantForAutofill()) { // View is not important for "regular" autofill, so we must check if Augmented Autofill // is enabled for the activity Loading Loading @@ -31860,6 +31877,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } /** * Gets the mode for determining whether this view is a credential. * * <p>See {@link #isCredential()}. * * @param isCredential Whether the view is a credential. * * @attr ref android.R.styleable#View_isCredential */ public void setIsCredential(boolean isCredential) { if (isCredential) { mPrivateFlags4 |= PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER; } else { mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER; } } /** * Gets the mode for determining whether this view is a credential. * * <p>See {@link #setIsCredential(boolean)}. * * @return false by default, or value passed to {@link #setIsCredential(boolean)}. * * @attr ref android.R.styleable#View_isCredential */ public boolean isCredential() { return ((mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER) == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER); } /** * Set whether this view enables automatic handwriting initiation. *
core/java/android/view/autofill/AutofillFeatureFlags.java 0 → 100644 +224 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.autofill; import android.annotation.TestApi; import android.provider.DeviceConfig; import android.text.TextUtils; import android.view.View; import com.android.internal.util.ArrayUtils; /** * Feature flags associated with autofill. * @hide */ @TestApi public class AutofillFeatureFlags { /** * {@code DeviceConfig} property used to set which Smart Suggestion modes for Augmented Autofill * are available. */ public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; /** * Sets how long (in ms) the augmented autofill service is bound while idle. * * <p>Use {@code 0} to keep it permanently bound. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT = "augmented_service_idle_unbind_timeout"; /** * Sets how long (in ms) the augmented autofill service request is killed if not replied. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT = "augmented_service_request_timeout"; /** * Sets allowed list for the autofill compatibility mode. * * The list of packages is {@code ":"} colon delimited, and each entry has the name of the * package and an optional list of url bar resource ids (the list is delimited by * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited). * * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 } * have 2 ids {@code url_foo} and {@code url_bas}) would be * {@code p1[url_bar]:p2:p3[url_foo,url_bas]} */ public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; /** * Indicates Fill dialog feature enabled or not. */ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; /** * Sets the autofill hints allowed list for the fields that can trigger the fill dialog * feature at Activity starting. * * The list of autofill hints is {@code ":"} colon delimited. * * <p>For example, a list with 3 hints {@code password}, {@code phone}, and * { @code emailAddress}, would be {@code password:phone:emailAddress} * * Note: By default the password field is enabled even there is no password hint in the list * * @see View#setAutofillHints(String...) * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS = "autofill_dialog_hints"; // START CREDENTIAL MANAGER FLAGS // /** * Indicates whether credential manager tagged views should be ignored from autofill structures. * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED} */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS = "autofill_credential_manager_ignore_views"; /** * Indicates CredentialManager feature enabled or not. * This is the overall feature flag. Individual behavior of credential manager may be controlled * via a different flag, but gated by this flag. */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED = "autofill_credential_manager_enabled"; /** * Indicates whether credential manager tagged views should suppress fill dialog. * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED} * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG = "autofill_credential_manager_suppress_fill_dialog"; /** * Indicates whether credential manager tagged views should suppress save dialog. * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED} * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_SAVE_DIALOG = "autofill_credential_manager_suppress_save_dialog"; // END CREDENTIAL MANAGER FLAGS // /** * Sets a value of delay time to show up the inline tooltip view. * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY = "autofill_inline_tooltip_first_show_delay"; private static final String DIALOG_HINTS_DELIMITER = ":"; private static final boolean DEFAULT_HAS_FILL_DIALOG_UI_FEATURE = false; private static final String DEFAULT_FILL_DIALOG_ENABLED_HINTS = ""; // CREDENTIAL MANAGER DEFAULTS // Credential manager is enabled by default so as to allow testing by app developers private static final boolean DEFAULT_CREDENTIAL_MANAGER_ENABLED = true; private static final boolean DEFAULT_CREDENTIAL_MANAGER_IGNORE_VIEWS = true; private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG = false; private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_SAVE_DIALOG = false; // END CREDENTIAL MANAGER DEFAULTS private AutofillFeatureFlags() {}; /** * Whether the fill dialog feature is enabled or not * * @hide */ public static boolean isFillDialogEnabled() { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED, DEFAULT_HAS_FILL_DIALOG_UI_FEATURE); } /** * Gets fill dialog enabled hints. * * @hide */ public static String[] getFillDialogEnabledHints() { final String dialogHints = DeviceConfig.getString( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS, DEFAULT_FILL_DIALOG_ENABLED_HINTS); if (TextUtils.isEmpty(dialogHints)) { return new String[0]; } return ArrayUtils.filter(dialogHints.split(DIALOG_HINTS_DELIMITER), String[]::new, (str) -> !TextUtils.isEmpty(str)); } /** * Whether the Credential Manager feature is enabled or not * * @hide */ public static boolean isCredentialManagerEnabled() { return DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED, DEFAULT_CREDENTIAL_MANAGER_ENABLED); } /** * Whether credential manager tagged views should be ignored for autofill structure. * * @hide */ public static boolean shouldIgnoreCredentialViews() { return isCredentialManagerEnabled() && DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS, DEFAULT_CREDENTIAL_MANAGER_IGNORE_VIEWS); } /** * Whether credential manager tagged views should not trigger fill dialog requests. * * @hide */ public static boolean isFillDialogDisabledForCredentialManager() { return isCredentialManagerEnabled() && DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG, DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_DIALOG); } }
core/java/android/view/autofill/AutofillManager.java +20 −109 Original line number Diff line number Diff line Loading @@ -60,7 +60,6 @@ import android.os.Looper; import android.os.Parcelable; import android.os.RemoteException; import android.os.SystemClock; import android.provider.DeviceConfig; import android.service.autofill.AutofillService; import android.service.autofill.FillCallback; import android.service.autofill.FillEventHistory; Loading Loading @@ -450,88 +449,6 @@ public final class AutofillManager { @Retention(RetentionPolicy.SOURCE) public @interface SmartSuggestionMode {} /** * {@code DeviceConfig} property used to set which Smart Suggestion modes for Augmented Autofill * are available. * * @hide */ @TestApi public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes"; /** * Sets how long (in ms) the augmented autofill service is bound while idle. * * <p>Use {@code 0} to keep it permanently bound. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT = "augmented_service_idle_unbind_timeout"; /** * Sets how long (in ms) the augmented autofill service request is killed if not replied. * * @hide */ public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT = "augmented_service_request_timeout"; /** * Sets allowed list for the autofill compatibility mode. * * The list of packages is {@code ":"} colon delimited, and each entry has the name of the * package and an optional list of url bar resource ids (the list is delimited by * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited). * * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 } * have 2 ids {@code url_foo} and {@code url_bas}) would be * {@code p1[url_bar]:p2:p3[url_foo,url_bas]} * * @hide */ @TestApi public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "compat_mode_allowed_packages"; /** * Sets the fill dialog feature enabled or not. * * @hide */ @TestApi public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled"; /** * Sets the autofill hints allowed list for the fields that can trigger the fill dialog * feature at Activity starting. * * The list of autofill hints is {@code ":"} colon delimited. * * <p>For example, a list with 3 hints {@code password}, {@code phone}, and * {@code emailAddress}, would be {@code password:phone:emailAddress} * * Note: By default the password field is enabled even there is no password hint in the list * * @see View#setAutofillHints(String...) * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS = "autofill_dialog_hints"; /** * Sets a value of delay time to show up the inline tooltip view. * * @hide */ public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY = "autofill_inline_tooltip_first_show_delay"; private static final String DIALOG_HINTS_DELIMITER = ":"; /** @hide */ public static final int RESULT_OK = 0; /** @hide */ Loading Loading @@ -634,9 +551,6 @@ public final class AutofillManager { */ public static final int NO_SESSION = Integer.MAX_VALUE; private static final boolean HAS_FILL_DIALOG_UI_FEATURE_DEFAULT = false; private static final String FILL_DIALOG_ENABLED_DEFAULT_HINTS = ""; private final IAutoFillManager mService; private final Object mLock = new Object(); Loading Loading @@ -891,11 +805,8 @@ public final class AutofillManager { mOptions = context.getAutofillOptions(); mIsFillRequested = new AtomicBoolean(false); mIsFillDialogEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED, HAS_FILL_DIALOG_UI_FEATURE_DEFAULT); mFillDialogEnabledHints = getFillDialogEnabledHints(); mIsFillDialogEnabled = AutofillFeatureFlags.isFillDialogEnabled(); mFillDialogEnabledHints = AutofillFeatureFlags.getFillDialogEnabledHints(); if (sDebug) { Log.d(TAG, "Fill dialog is enabled:" + mIsFillDialogEnabled + ", hints=" + Arrays.toString(mFillDialogEnabledHints)); Loading @@ -907,19 +818,6 @@ public final class AutofillManager { } } private String[] getFillDialogEnabledHints() { final String dialogHints = DeviceConfig.getString( DeviceConfig.NAMESPACE_AUTOFILL, DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS, FILL_DIALOG_ENABLED_DEFAULT_HINTS); if (TextUtils.isEmpty(dialogHints)) { return new String[0]; } return ArrayUtils.filter(dialogHints.split(DIALOG_HINTS_DELIMITER), String[]::new, (str) -> !TextUtils.isEmpty(str)); } /** * @hide */ Loading Loading @@ -1190,16 +1088,28 @@ public final class AutofillManager { } /** * The {@link #DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or the view have * the allowed autofill hints, performs a fill request to know there is any field supported * fill dialog. * The {@link AutofillFeatureFlags#DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or * the view have the allowed autofill hints, performs a fill request to know there is any field * supported fill dialog. * * @hide */ public void notifyViewEnteredForFillDialog(View v) { if (sDebug) { Log.d(TAG, "notifyViewEnteredForFillDialog:" + v.getAutofillId()); } if (!hasAutofillFeature()) { return; } if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager() && v.isCredential()) { if (sDebug) { Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:" + v.getAutofillId().toString()); } return; } synchronized (mLock) { if (mTrackedViews != null) { // To support the fill dialog can show for the autofillable Views in Loading Loading @@ -1227,8 +1137,8 @@ public final class AutofillManager { synchronized (mLock) { // To match the id of the IME served view, used AutofillId.NO_AUTOFILL_ID on prefill // request, because IME will reset the id of IME served view to 0 when activity // start and does not focus on any view. If the id of the prefill request is // not match to the IME served view's, Autofill will be blocking to wait inline // start and does not focus on any view. If the id of the prefill request does // not match the IME served view's, Autofill will be blocking to wait inline // request from the IME. notifyViewEnteredLocked(/* view= */ null, AutofillId.NO_AUTOFILL_ID, /* bounds= */ null, /* value= */ null, flags); Loading Loading @@ -4075,6 +3985,7 @@ public final class AutofillManager { } } @Override public void notifyFillDialogTriggerIds(List<AutofillId> ids) { final AutofillManager afm = mAfm.get(); if (afm != null) { Loading