Merge "Adding experiment flags for optimization part of autofill for all apps" into udc-dev

This commit is contained in:
Haoran Zhang
2023-03-09 18:18:44 +00:00
committed by Android (Google) Code Review
3 changed files with 123 additions and 19 deletions

View File

@@ -163,6 +163,7 @@ import android.view.translation.ViewTranslationCallback;
import android.view.translation.ViewTranslationRequest;
import android.view.translation.ViewTranslationResponse;
import android.widget.Checkable;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ScrollBarDrawable;
import android.window.OnBackInvokedDispatcher;
@@ -10356,7 +10357,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final AutofillManager afm = getAutofillManager();
// keep default behavior
if (afm == null) return false;
return afm.isMatchingAutofillableHeuristics(this);
return afm.isMatchingAutofillableHeuristicsForNotImportantViews(this);
}
private boolean isAutofillable() {
@@ -10372,26 +10373,47 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return false;
}
// Experiment imeAction heuristic on important views. If the important view doesn't pass
// heuristic check, also check augmented autofill in case augmented autofill is enabled
// for the activity
// TODO: refactor to have both important views and not important views use the same
// heuristic check
if (isImportantForAutofill()
&& afm.isTriggerFillRequestOnFilteredImportantViewsEnabled()
&& this instanceof EditText
&& !afm.isPassingImeActionCheck((EditText) this)
&& !notifyAugmentedAutofillIfNeeded(afm)) {
// TODO: add a log to indicate what has filtered out the view
return false;
}
if (!isImportantForAutofill()) {
// If view matches heuristics and is not denied, it will be treated same as view that's
// important for autofill
if (afm.isMatchingAutofillableHeuristics(this)
if (afm.isMatchingAutofillableHeuristicsForNotImportantViews(this)
&& !afm.isActivityDeniedForAutofillForUnimportantView()) {
return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
}
// View is not important for "regular" autofill, so we must check if Augmented Autofill
// is enabled for the activity
final AutofillOptions options = mContext.getAutofillOptions();
if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
if (!notifyAugmentedAutofillIfNeeded(afm)){
return false;
}
afm.notifyViewEnteredForAugmentedAutofill(this);
}
return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
}
/** @hide **/
public boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
final AutofillOptions options = mContext.getAutofillOptions();
if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
return false;
}
afm.notifyViewEnteredForAugmentedAutofill(this);
return true;
}
/** @hide */
public boolean canNotifyAutofillEnterExitEvent() {
return isAutofillable() && isAttachedToWindow();

View File

@@ -155,6 +155,14 @@ public class AutofillFeatureFlags {
public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW =
"trigger_fill_request_on_unimportant_view";
/**
* Whether to apply heuristic check on important views.
*
* @hide
*/
public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_FILTERED_IMPORTANT_VIEWS =
"trigger_fill_request_on_filtered_important_views";
/**
* Continas imeAction ids that is irrelevant for autofill. For example, ime_action_search. We
* use this to avoid trigger fill request on unimportant views.
@@ -167,6 +175,14 @@ public class AutofillFeatureFlags {
@SuppressLint("IntentName")
public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS =
"non_autofillable_ime_action_ids";
/**
* Whether to enable autofill on all view types (not just checkbox, spinner, datepicker etc...)
*
* @hide
*/
public static final String DEVICE_CONFIG_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES =
"should_enable_autofill_on_all_view_types";
// END AUTOFILL FOR ALL APPS FLAGS //
@@ -314,6 +330,28 @@ public class AutofillFeatureFlags {
DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW, false);
}
/**
* Whether to apply heuristic check on important views before triggering fill request
*
* @hide
*/
public static boolean isTriggerFillRequestOnFilteredImportantViewsEnabled() {
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_AUTOFILL,
DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_FILTERED_IMPORTANT_VIEWS, false);
}
/**
* Whether to enable autofill on all view types.
*
* @hide
*/
public static boolean shouldEnableAutofillOnAllViewTypes(){
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_AUTOFILL,
DEVICE_CONFIG_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES, false);
}
/**
* Get the non-autofillable ime actions from flag. This will be used in filtering
* condition to trigger fill request.

View File

@@ -674,6 +674,12 @@ public final class AutofillManager {
// Indicate whether trigger fill request on unimportant views is enabled
private boolean mIsTriggerFillRequestOnUnimportantViewEnabled = false;
// Indicate whether to apply heuristic check on important views before trigger fill request
private boolean mIsTriggerFillRequestOnFilteredImportantViewsEnabled;
// Indicate whether to enable autofill for all view types
private boolean mShouldEnableAutofillOnAllViewTypes;
// A set containing all non-autofillable ime actions passed by flag
private Set<String> mNonAutofillableImeActionIdSet = new ArraySet<>();
@@ -855,6 +861,12 @@ public final class AutofillManager {
mIsTriggerFillRequestOnUnimportantViewEnabled =
AutofillFeatureFlags.isTriggerFillRequestOnUnimportantViewEnabled();
mIsTriggerFillRequestOnFilteredImportantViewsEnabled =
AutofillFeatureFlags.isTriggerFillRequestOnFilteredImportantViewsEnabled();
mShouldEnableAutofillOnAllViewTypes =
AutofillFeatureFlags.shouldEnableAutofillOnAllViewTypes();
mNonAutofillableImeActionIdSet =
AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();
@@ -865,14 +877,39 @@ public final class AutofillManager {
mIsPackageFullyDeniedForAutofillForUnimportantView =
isPackageFullyDeniedForAutofillForUnimportantView(denyListString, packageName);
mIsPackagePartiallyDeniedForAutofillForUnimportantView =
isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
if (!mIsPackageFullyDeniedForAutofillForUnimportantView) {
mIsPackagePartiallyDeniedForAutofillForUnimportantView =
isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
}
if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
setDeniedActivitySetWithDenyList(denyListString, packageName);
}
}
/**
* Whether to apply heuristic check on important views before triggering fill request
*
* @hide
*/
public boolean isTriggerFillRequestOnFilteredImportantViewsEnabled() {
return mIsTriggerFillRequestOnFilteredImportantViewsEnabled;
}
/**
* Whether view passes the imeAction check
*
* @hide
*/
public boolean isPassingImeActionCheck(EditText editText) {
final int actionId = editText.getImeOptions();
if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
// TODO: add a log to indicate what has filtered out the view
return false;
}
return true;
}
private boolean isPackageFullyDeniedForAutofillForUnimportantView(
@NonNull String denyListString, @NonNull String packageName) {
// If "PackageName:;" is in the string, then it means the package name is in denylist
@@ -957,25 +994,32 @@ public final class AutofillManager {
*
* @hide
*/
public final boolean isMatchingAutofillableHeuristics(@NonNull View view) {
public final boolean isMatchingAutofillableHeuristicsForNotImportantViews(@NonNull View view) {
if (!mIsTriggerFillRequestOnUnimportantViewEnabled) {
return false;
}
// TODO: remove the autofill type check when this function is applied on both important and
// not important views.
// This check is needed here because once the view type check is lifted, addiditional
// unimportant views will be added to the assist structure which may cuase system health
// regression (viewGroup#populateChidlrenForAutofill() calls this function to decide whether
// to include child view)
if (view.getAutofillType() == View.AUTOFILL_TYPE_NONE) return false;
if (view instanceof EditText) {
final int actionId = ((EditText) view).getImeOptions();
if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
return false;
}
return true;
return isPassingImeActionCheck((EditText) view);
}
if (view instanceof CheckBox
|| view instanceof Spinner
|| view instanceof DatePicker
|| view instanceof TimePicker
|| view instanceof RadioGroup) {
|| view instanceof Spinner
|| view instanceof DatePicker
|| view instanceof TimePicker
|| view instanceof RadioGroup) {
return true;
}
return false;
return mShouldEnableAutofillOnAllViewTypes;
}