diff options
| -rw-r--r-- | core/api/current.txt | 2 | ||||
| -rw-r--r-- | core/api/test-current.txt | 11 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 48 | ||||
| -rw-r--r-- | core/java/android/view/autofill/AutofillFeatureFlags.java | 224 | ||||
| -rw-r--r-- | core/java/android/view/autofill/AutofillManager.java | 129 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/inline/InlineTooltipUi.java | 2 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java | 94 | ||||
| -rw-r--r-- | services/autofill/java/com/android/server/autofill/AutofillManagerService.java | 17 |
8 files changed, 406 insertions, 121 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 19123bba2b5d..50255955f651 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -51415,6 +51415,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(); @@ -51648,6 +51649,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); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index d25c3f5bf538..6ea1dde30996 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -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); @@ -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 diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 01984571a8f4..c73cfc22104b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -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; @@ -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 */ @@ -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)); @@ -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 @@ -31861,6 +31878,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. * * For a view with an active {@link InputConnection}, if auto handwriting is enabled then diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java new file mode 100644 index 000000000000..59ad15139de1 --- /dev/null +++ b/core/java/android/view/autofill/AutofillFeatureFlags.java @@ -0,0 +1,224 @@ +/* + * 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); + } +} diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index a92bc945c004..58e7a70b155c 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -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; @@ -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 */ @@ -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(); @@ -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)); @@ -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 */ @@ -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 @@ -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); @@ -4075,6 +3985,7 @@ public final class AutofillManager { } } + @Override public void notifyFillDialogTriggerIds(List<AutofillId> ids) { final AutofillManager afm = mAfm.get(); if (afm != null) { diff --git a/core/java/com/android/internal/view/inline/InlineTooltipUi.java b/core/java/com/android/internal/view/inline/InlineTooltipUi.java index 836786d7c592..7e12574e08f1 100644 --- a/core/java/com/android/internal/view/inline/InlineTooltipUi.java +++ b/core/java/com/android/internal/view/inline/InlineTooltipUi.java @@ -15,7 +15,7 @@ */ package com.android.internal.view.inline; -import static android.view.autofill.AutofillManager.DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY; +import static android.view.autofill.AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY; import static android.view.autofill.Helper.sVerbose; import android.annotation.NonNull; diff --git a/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java b/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java new file mode 100644 index 000000000000..e03b722c9c6c --- /dev/null +++ b/core/tests/coretests/src/android/view/autofill/AutofillFeatureFlagsTest.java @@ -0,0 +1,94 @@ +/* + * 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 static com.google.common.truth.Truth.assertThat; + +import android.provider.DeviceConfig; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Tests for {@link AutofillFeatureFlags} + * + * run: atest FrameworksCoreTests:android.view.autofill.AutofillFeatureFlagsTest + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AutofillFeatureFlagsTest { + + @Test + public void testGetFillDialogEnabledHintsEmpty() { + setFillDialogHints(""); + String[] fillDialogHints = AutofillFeatureFlags.getFillDialogEnabledHints(); + assertThat(fillDialogHints).isEmpty(); + } + + @Test + public void testGetFillDialogEnabledHintsTwoValues() { + setFillDialogHints("password:creditCardNumber"); + String[] fillDialogHints = AutofillFeatureFlags.getFillDialogEnabledHints(); + assertThat(fillDialogHints.length).isEqualTo(2); + assertThat(fillDialogHints[0]).isEqualTo("password"); + assertThat(fillDialogHints[1]).isEqualTo("creditCardNumber"); + } + + @Test + public void testIsCredentialManagerEnabled() { + setCredentialManagerEnabled(false); + assertThat(AutofillFeatureFlags.isCredentialManagerEnabled()).isFalse(); + setCredentialManagerEnabled(true); + assertThat(AutofillFeatureFlags.isCredentialManagerEnabled()).isTrue(); + } + + @Test + public void testShouldIgnoreCredentialManagerViews() { + setCredentialManagerEnabled(false); + setIgnoreCredentialManagerViews(true); + // Overall feature is disabled, so we shouldn't ignore views. + assertThat(AutofillFeatureFlags.shouldIgnoreCredentialViews()).isFalse(); + setCredentialManagerEnabled(true); + assertThat(AutofillFeatureFlags.shouldIgnoreCredentialViews()).isTrue(); + } + + private static void setFillDialogHints(String value) { + setDeviceConfig( + AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS, + value); + } + + private static void setCredentialManagerEnabled(boolean value) { + setDeviceConfig( + AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED, + String.valueOf(value)); + } + + private static void setIgnoreCredentialManagerViews(boolean value) { + setDeviceConfig( + AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS, + String.valueOf(value)); + } + + private static void setDeviceConfig(String key, String value) { + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_AUTOFILL, key, value, /* makeDefault */ false); + } +} diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index 54f77b1e7928..6b61e978ea7b 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -67,6 +67,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.TimeUtils; +import android.view.autofill.AutofillFeatureFlags; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillManager.AutofillCommitReason; @@ -298,12 +299,12 @@ public final class AutofillManagerService private void onDeviceConfigChange(@NonNull Set<String> keys) { for (String key : keys) { switch (key) { - case AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES: - case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT: - case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT: + case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES: + case AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT: + case AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT: setDeviceConfigProperties(); break; - case AutofillManager.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES: + case AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES: updateCachedServices(); break; default: @@ -567,15 +568,15 @@ public final class AutofillManagerService synchronized (mLock) { mAugmentedServiceIdleUnbindTimeoutMs = DeviceConfig.getInt( DeviceConfig.NAMESPACE_AUTOFILL, - AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT, + AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT, (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS); mAugmentedServiceRequestTimeoutMs = DeviceConfig.getInt( DeviceConfig.NAMESPACE_AUTOFILL, - AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT, + AutofillFeatureFlags.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT, DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS); mSupportedSmartSuggestionModes = DeviceConfig.getInt( DeviceConfig.NAMESPACE_AUTOFILL, - AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES, + AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES, AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM); if (verbose) { Slog.v(mTag, "setDeviceConfigProperties(): " @@ -729,7 +730,7 @@ public final class AutofillManagerService private String getAllowedCompatModePackagesFromDeviceConfig() { String config = DeviceConfig.getString( DeviceConfig.NAMESPACE_AUTOFILL, - AutofillManager.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES, + AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES, /* defaultValue */ null); if (!TextUtils.isEmpty(config)) { return config; |