1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view.autofill;
18 
19 import android.annotation.SuppressLint;
20 import android.annotation.TestApi;
21 import android.provider.DeviceConfig;
22 import android.text.TextUtils;
23 import android.util.ArraySet;
24 import android.view.View;
25 
26 import com.android.internal.util.ArrayUtils;
27 
28 import java.util.Arrays;
29 import java.util.Set;
30 
31 /**
32  * Feature flags associated with autofill.
33  * @hide
34  */
35 @TestApi
36 public class AutofillFeatureFlags {
37 
38     /**
39      * {@code DeviceConfig} property used to set which Smart Suggestion modes for Augmented Autofill
40      * are available.
41      */
42     public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES =
43             "smart_suggestion_supported_modes";
44 
45     /**
46      * Sets how long (in ms) the augmented autofill service is bound while idle.
47      *
48      * <p>Use {@code 0} to keep it permanently bound.
49      *
50      * @hide
51      */
52     public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT =
53             "augmented_service_idle_unbind_timeout";
54 
55     /**
56      * Sets how long (in ms) the augmented autofill service request is killed if not replied.
57      *
58      * @hide
59      */
60     public static final String DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT =
61             "augmented_service_request_timeout";
62 
63     /**
64      * Sets allowed list for the autofill compatibility mode.
65      *
66      * The list of packages is {@code ":"} colon delimited, and each entry has the name of the
67      * package and an optional list of url bar resource ids (the list is delimited by
68      * brackets&mdash{@code [} and {@code ]}&mdash and is also comma delimited).
69      *
70      * <p>For example, a list with 3 packages {@code p1}, {@code p2}, and {@code p3}, where
71      * package {@code p1} have one id ({@code url_bar}, {@code p2} has none, and {@code p3 }
72      * have 2 ids {@code url_foo} and {@code url_bas}) would be
73      * {@code p1[url_bar]:p2:p3[url_foo,url_bas]}
74      */
75     public static final String DEVICE_CONFIG_AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES =
76             "compat_mode_allowed_packages";
77 
78     /**
79      * Indicates Fill dialog feature enabled or not.
80      */
81     public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED =
82             "autofill_dialog_enabled";
83 
84     /**
85      * Sets the autofill hints allowed list for the fields that can trigger the fill dialog
86      * feature at Activity starting.
87      *
88      * The list of autofill hints is {@code ":"} colon delimited.
89      *
90      *  <p>For example, a list with 3 hints {@code password}, {@code phone}, and
91      * { @code emailAddress}, would be {@code password:phone:emailAddress}
92      *
93      * Note: By default the password field is enabled even there is no password hint in the list
94      *
95      * @see View#setAutofillHints(String...)
96      * @hide
97      */
98     public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS =
99             "autofill_dialog_hints";
100 
101     // START CREDENTIAL MANAGER FLAGS //
102     /**
103      * (deprecated) Indicates whether credential manager tagged views should be ignored from
104      * autofill structures.This flag is further gated by
105      * {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED}
106      *
107      * TODO(b/280661772): Remove this flag once API change is allowed
108      */
109     public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS =
110             "autofill_credential_manager_ignore_views";
111 
112     /**
113      * (deprecated) Indicates CredentialManager feature enabled or not.
114      * This is the overall feature flag. Individual behavior of credential manager may be controlled
115      * via a different flag, but gated by this flag.
116      *
117      * TODO(b/280661772): Remove this flag once API change is allowed
118      */
119     public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED =
120             "autofill_credential_manager_enabled";
121 
122     /**
123      * Indicates whether credential manager tagged views should suppress fill and save dialog.
124      * This flag is further gated by {@link #DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED}
125      *
126      * @hide
127      */
128     public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_AND_SAVE_DIALOG =
129             "autofill_credential_manager_suppress_fill_and_save_dialog";
130     // END CREDENTIAL MANAGER FLAGS //
131 
132     // START AUTOFILL FOR ALL APPS FLAGS //
133     /**
134      * Sets the list of activities and packages denied for autofill
135      *
136      * The list is {@code ";"} colon delimited. Activities under a package is separated by
137      * {@code ","}. Each package name much be followed by a {@code ":"}. Each package entry must be
138      * ends with a {@code ";"}
139      *
140      * <p>For example, a list with only 1 package would be, {@code Package1:;}. A list with one
141      * denied activity {@code Activity1} under {@code Package1} and a full denied package
142      * {@code Package2} would be {@code Package1:Activity1;Package2:;}
143      */
144     public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW =
145             "package_deny_list_for_unimportant_view";
146 
147     /**
148      * Sets the list of activities and packages allowed for autofill. The format is same with
149      * {@link #DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW}
150      *
151      * @hide
152      */
153     public static final String DEVICE_CONFIG_PACKAGE_AND_ACTIVITY_ALLOWLIST_FOR_TRIGGERING_FILL_REQUEST =
154             "package_and_activity_allowlist_for_triggering_fill_request";
155 
156     /**
157      * Whether the heuristics check for view is enabled
158      */
159     public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW =
160             "trigger_fill_request_on_unimportant_view";
161 
162     /**
163      * Whether to apply heuristic check on important views.
164      *
165      * @hide
166      */
167     public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_FILTERED_IMPORTANT_VIEWS =
168             "trigger_fill_request_on_filtered_important_views";
169 
170     /**
171      * Continas imeAction ids that is irrelevant for autofill. For example, ime_action_search. We
172      * use this to avoid trigger fill request on unimportant views.
173      *
174      * The list is {@code ","} delimited.
175      *
176      * <p> For example, a imeAction list could be "2,3,4", corresponding to ime_action definition
177      * in {@link android.view.inputmethod.EditorInfo.java}</p>
178      */
179     @SuppressLint("IntentName")
180     public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS =
181             "non_autofillable_ime_action_ids";
182 
183     /**
184      * Whether to enable autofill on all view types (not just checkbox, spinner, datepicker etc...)
185      *
186      * @hide
187      */
188     public static final String DEVICE_CONFIG_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES =
189             "should_enable_autofill_on_all_view_types";
190 
191     /**
192      * Whether to enable multi-line filter when checking if view is autofillable
193      *
194      * @hide
195      */
196     public static final String DEVICE_CONFIG_MULTILINE_FILTER_ENABLED =
197             "multiline_filter_enabled";
198 
199     /**
200      * Whether include all autofill type not none views in assist structure
201      *
202      * @hide
203      */
204     public static final String
205         DEVICE_CONFIG_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE =
206             "include_all_autofill_type_not_none_views_in_assist_structure";
207 
208     /**
209      * Whether include all views in assist structure
210      *
211      * @hide
212      */
213     public static final String
214         DEVICE_CONFIG_INCLUDE_ALL_VIEWS_IN_ASSIST_STRUCTURE =
215             "include_all_views_in_assist_structure";
216 
217     // END AUTOFILL FOR ALL APPS FLAGS //
218 
219 
220     // START AUTOFILL PCC CLASSIFICATION FLAGS
221 
222     /**
223      * Sets the fill dialog feature enabled or not.
224      */
225     public static final String DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED =
226             "pcc_classification_enabled";
227 
228     /**
229      * Give preference to autofill provider's detection.
230      * @hide
231      */
232     public static final String DEVICE_CONFIG_PREFER_PROVIDER_OVER_PCC = "prefer_provider_over_pcc";
233 
234     /**
235      * Indicates the Autofill Hints that would be requested by the service from the Autofill
236      * Provider.
237      */
238     public static final String DEVICE_CONFIG_AUTOFILL_PCC_FEATURE_PROVIDER_HINTS =
239             "pcc_classification_hints";
240 
241     /**
242      * Use data from secondary source if primary not present .
243      * For eg: if we prefer PCC over provider, and PCC detection didn't classify a field, however,
244      * autofill provider did, this flag would decide whether we use that result, and show some
245      * presentation for that particular field.
246      * @hide
247      */
248     public static final String DEVICE_CONFIG_PCC_USE_FALLBACK = "pcc_use_fallback";
249 
250     // END AUTOFILL PCC CLASSIFICATION FLAGS
251 
252 
253     /**
254      * Sets a value of delay time to show up the inline tooltip view.
255      *
256      * @hide
257      */
258     public static final String DEVICE_CONFIG_AUTOFILL_TOOLTIP_SHOW_UP_DELAY =
259             "autofill_inline_tooltip_first_show_delay";
260 
261     private static final String DIALOG_HINTS_DELIMITER = ":";
262 
263     private static final boolean DEFAULT_HAS_FILL_DIALOG_UI_FEATURE = false;
264     private static final String DEFAULT_FILL_DIALOG_ENABLED_HINTS = "";
265 
266 
267     // CREDENTIAL MANAGER DEFAULTS
268     private static final boolean DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_AND_SAVE_DIALOG = true;
269     // END CREDENTIAL MANAGER DEFAULTS
270 
271 
272     // AUTOFILL PCC CLASSIFICATION FLAGS DEFAULTS
273     // Default for whether the pcc classification is enabled for autofill.
274     /** @hide */
275     public static final boolean DEFAULT_AUTOFILL_PCC_CLASSIFICATION_ENABLED = false;
276     // END AUTOFILL PCC CLASSIFICATION FLAGS DEFAULTS
277 
278     // AUTOFILL FOR ALL APPS DEFAULTS
279     private static final boolean DEFAULT_AFAA_ON_UNIMPORTANT_VIEW_ENABLED = true;
280     private static final boolean DEFAULT_AFAA_ON_IMPORTANT_VIEW_ENABLED = true;
281     private static final String DEFAULT_AFAA_DENYLIST = "";
282     private static final String DEFAULT_AFAA_ALLOWLIST = "";
283     private static final String DEFAULT_AFAA_NON_AUTOFILLABLE_IME_ACTIONS = "3,4";
284     private static final boolean DEFAULT_AFAA_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES = true;
285     private static final boolean DEFAULT_AFAA_SHOULD_ENABLE_MULTILINE_FILTER = true;
286     private static final boolean
287             DEFAULT_AFAA_SHOULD_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE = true;
288     // END AUTOFILL FOR ALL APPS DEFAULTS
289 
AutofillFeatureFlags()290     private AutofillFeatureFlags() {};
291 
292     /**
293      * Whether the fill dialog feature is enabled or not
294      *
295      * @hide
296      */
isFillDialogEnabled()297     public static boolean isFillDialogEnabled() {
298         return DeviceConfig.getBoolean(
299                 DeviceConfig.NAMESPACE_AUTOFILL,
300                 DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED,
301                 DEFAULT_HAS_FILL_DIALOG_UI_FEATURE);
302     }
303 
304     /**
305      * Gets fill dialog enabled hints.
306      *
307      * @hide
308      */
getFillDialogEnabledHints()309     public static String[] getFillDialogEnabledHints() {
310         final String dialogHints = DeviceConfig.getString(
311                 DeviceConfig.NAMESPACE_AUTOFILL,
312                 DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS,
313                 DEFAULT_FILL_DIALOG_ENABLED_HINTS);
314         if (TextUtils.isEmpty(dialogHints)) {
315             return new String[0];
316         }
317 
318         return ArrayUtils.filter(dialogHints.split(DIALOG_HINTS_DELIMITER), String[]::new,
319                 (str) -> !TextUtils.isEmpty(str));
320     }
321 
322     /* starts credman flag getter function */
323     /**
324      * Whether credential manager tagged views should not trigger fill dialog requests.
325      *
326      * @hide
327      */
isFillAndSaveDialogDisabledForCredentialManager()328     public static boolean isFillAndSaveDialogDisabledForCredentialManager() {
329         return DeviceConfig.getBoolean(
330                     DeviceConfig.NAMESPACE_AUTOFILL,
331                     DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_SUPPRESS_FILL_AND_SAVE_DIALOG,
332                     DEFAULT_CREDENTIAL_MANAGER_SUPPRESS_FILL_AND_SAVE_DIALOG);
333     }
334     /* ends credman flag getter function */
335 
336     /**
337      * Whether triggering fill request on unimportant view is enabled.
338      *
339      * @hide
340      */
isTriggerFillRequestOnUnimportantViewEnabled()341     public static boolean isTriggerFillRequestOnUnimportantViewEnabled() {
342         return DeviceConfig.getBoolean(
343             DeviceConfig.NAMESPACE_AUTOFILL,
344             DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW,
345             DEFAULT_AFAA_ON_UNIMPORTANT_VIEW_ENABLED);
346     }
347 
348     /**
349      * Whether to apply heuristic check on important views before triggering fill request
350      *
351      * @hide
352      */
isTriggerFillRequestOnFilteredImportantViewsEnabled()353     public static boolean isTriggerFillRequestOnFilteredImportantViewsEnabled() {
354         return DeviceConfig.getBoolean(
355             DeviceConfig.NAMESPACE_AUTOFILL,
356             DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_FILTERED_IMPORTANT_VIEWS,
357             DEFAULT_AFAA_ON_IMPORTANT_VIEW_ENABLED);
358     }
359 
360     /**
361      * Whether to enable autofill on all view types.
362      *
363      * @hide
364      */
shouldEnableAutofillOnAllViewTypes()365     public static boolean shouldEnableAutofillOnAllViewTypes(){
366         return DeviceConfig.getBoolean(
367             DeviceConfig.NAMESPACE_AUTOFILL,
368             DEVICE_CONFIG_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES,
369             DEFAULT_AFAA_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES);
370     }
371 
372     /**
373      * Get the non-autofillable ime actions from flag. This will be used in filtering
374      * condition to trigger fill request.
375      *
376      * @hide
377      */
getNonAutofillableImeActionIdSetFromFlag()378     public static Set<String> getNonAutofillableImeActionIdSetFromFlag() {
379         final String mNonAutofillableImeActions = DeviceConfig.getString(
380                 DeviceConfig.NAMESPACE_AUTOFILL,
381                 DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS,
382                 DEFAULT_AFAA_NON_AUTOFILLABLE_IME_ACTIONS);
383         return new ArraySet<>(Arrays.asList(mNonAutofillableImeActions.split(",")));
384     }
385 
386     /**
387      * Get denylist string from flag.
388      *
389      * Note: This denylist works both on important view and not important views. The flag used here
390      * is legacy flag which will be replaced with soon.
391      *
392      * @hide
393      */
getDenylistStringFromFlag()394     public static String getDenylistStringFromFlag() {
395         return DeviceConfig.getString(
396             DeviceConfig.NAMESPACE_AUTOFILL,
397             DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW,
398             DEFAULT_AFAA_DENYLIST);
399     }
400 
401     /**
402      * Get autofill allowlist from flag
403      *
404      * @hide
405      */
getAllowlistStringFromFlag()406     public static String getAllowlistStringFromFlag() {
407         return DeviceConfig.getString(
408             DeviceConfig.NAMESPACE_AUTOFILL,
409             DEVICE_CONFIG_PACKAGE_AND_ACTIVITY_ALLOWLIST_FOR_TRIGGERING_FILL_REQUEST,
410             DEFAULT_AFAA_ALLOWLIST);
411     }
412     /**
413      * Whether include all views that have autofill type not none in assist structure.
414      *
415      * @hide
416      */
shouldIncludeAllViewsAutofillTypeNotNoneInAssistStructrue()417     public static boolean shouldIncludeAllViewsAutofillTypeNotNoneInAssistStructrue() {
418         return DeviceConfig.getBoolean(
419             DeviceConfig.NAMESPACE_AUTOFILL,
420             DEVICE_CONFIG_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE,
421             DEFAULT_AFAA_SHOULD_INCLUDE_ALL_AUTOFILL_TYPE_NOT_NONE_VIEWS_IN_ASSIST_STRUCTURE);
422     }
423 
424     /**
425      * Whether include all views in assist structure.
426      *
427      * @hide
428      */
shouldIncludeAllChildrenViewInAssistStructure()429     public static boolean shouldIncludeAllChildrenViewInAssistStructure() {
430         return DeviceConfig.getBoolean(
431             DeviceConfig.NAMESPACE_AUTOFILL,
432             DEVICE_CONFIG_INCLUDE_ALL_VIEWS_IN_ASSIST_STRUCTURE, false);
433     }
434 
435 
436     /**
437      * Whether should enable multi-line filter
438      *
439      * @hide
440      */
shouldEnableMultilineFilter()441     public static boolean shouldEnableMultilineFilter() {
442         return DeviceConfig.getBoolean(
443             DeviceConfig.NAMESPACE_AUTOFILL,
444             DEVICE_CONFIG_MULTILINE_FILTER_ENABLED,
445             DEFAULT_AFAA_SHOULD_ENABLE_MULTILINE_FILTER);
446     }
447 
448     // START AUTOFILL PCC CLASSIFICATION FUNCTIONS
449 
450     /**
451      * Whether Autofill PCC Detection is enabled.
452      *
453      * @hide
454      */
isAutofillPccClassificationEnabled()455     public static boolean isAutofillPccClassificationEnabled() {
456         // TODO(b/266379948): Add condition for checking whether device has PCC first
457 
458         return DeviceConfig.getBoolean(
459                 DeviceConfig.NAMESPACE_AUTOFILL,
460                 DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED,
461                 DEFAULT_AUTOFILL_PCC_CLASSIFICATION_ENABLED);
462     }
463 
464     // END AUTOFILL PCC CLASSIFICATION FUNCTIONS
465 }
466