Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d63dbda authored by Haoran Zhang's avatar Haoran Zhang
Browse files

Adding experiment flags for optimization part of autofill for all apps

For experiemnt, we added two flags:
1. Enable heuristic check on important views. This flag is default to
   false. If this flag is enabled, the imeAction check will also be
   applied on important for autofill views. We want to see if enabling
   this would decrease non-autofillable requests received by autofill
   providers, also check if there is any regressions.

2. Flag to indicate whether to have view type check on not important
   views. It's default to enabled. We wnat to see if disabling this
   would cause any regression.

For potential bug line, we will be only checking package partially
denied if package is not fully denied. In current logic, if package is
fully denied, it will always be partially denied. Because whether it's
fully denied is checked by if "package:;" is in denylist and partial
denied is checked by if "package:" is in denylist.

bug:265186343

Change-Id: I613d3a76af1252903cd5a5b12746e1ae8ad33615
parent 01f114e1
Loading
Loading
Loading
Loading
+28 −6
Original line number Original line Diff line number Diff line
@@ -163,6 +163,7 @@ import android.view.translation.ViewTranslationCallback;
import android.view.translation.ViewTranslationRequest;
import android.view.translation.ViewTranslationRequest;
import android.view.translation.ViewTranslationResponse;
import android.view.translation.ViewTranslationResponse;
import android.widget.Checkable;
import android.widget.Checkable;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.FrameLayout;
import android.widget.ScrollBarDrawable;
import android.widget.ScrollBarDrawable;
import android.window.OnBackInvokedDispatcher;
import android.window.OnBackInvokedDispatcher;
@@ -10356,7 +10357,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        final AutofillManager afm = getAutofillManager();
        final AutofillManager afm = getAutofillManager();
        // keep default behavior
        // keep default behavior
        if (afm == null) return false;
        if (afm == null) return false;
        return afm.isMatchingAutofillableHeuristics(this);
        return afm.isMatchingAutofillableHeuristicsForNotImportantViews(this);
    }
    }
    private boolean isAutofillable() {
    private boolean isAutofillable() {
@@ -10372,26 +10373,47 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return false;
            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 (!isImportantForAutofill()) {
            // If view matches heuristics and is not denied, it will be treated same as view that's
            // If view matches heuristics and is not denied, it will be treated same as view that's
            // important for autofill
            // important for autofill
            if (afm.isMatchingAutofillableHeuristics(this)
            if (afm.isMatchingAutofillableHeuristicsForNotImportantViews(this)
                    && !afm.isActivityDeniedForAutofillForUnimportantView()) {
                    && !afm.isActivityDeniedForAutofillForUnimportantView()) {
                return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
                return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
            }
            }
            // View is not important for "regular" autofill, so we must check if Augmented Autofill
            // View is not important for "regular" autofill, so we must check if Augmented Autofill
            // is enabled for the activity
            // is enabled for the activity
            final AutofillOptions options = mContext.getAutofillOptions();
            if (!notifyAugmentedAutofillIfNeeded(afm)){
            if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
                return false;
                return false;
            }
            }
            afm.notifyViewEnteredForAugmentedAutofill(this);
        }
        }
        return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
        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 */
    /** @hide */
    public boolean canNotifyAutofillEnterExitEvent() {
    public boolean canNotifyAutofillEnterExitEvent() {
        return isAutofillable() && isAttachedToWindow();
        return isAutofillable() && isAttachedToWindow();
+38 −0
Original line number Original line Diff line number Diff line
@@ -155,6 +155,14 @@ public class AutofillFeatureFlags {
    public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW =
    public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW =
            "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
     * Continas imeAction ids that is irrelevant for autofill. For example, ime_action_search. We
     * use this to avoid trigger fill request on unimportant views.
     * use this to avoid trigger fill request on unimportant views.
@@ -167,6 +175,14 @@ public class AutofillFeatureFlags {
    @SuppressLint("IntentName")
    @SuppressLint("IntentName")
    public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS =
    public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS =
            "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 //
    // END AUTOFILL FOR ALL APPS FLAGS //




@@ -314,6 +330,28 @@ public class AutofillFeatureFlags {
            DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW, false);
            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
     * Get the non-autofillable ime actions from flag. This will be used in filtering
     * condition to trigger fill request.
     * condition to trigger fill request.
+57 −13
Original line number Original line Diff line number Diff line
@@ -674,6 +674,12 @@ public final class AutofillManager {
    // Indicate whether trigger fill request on unimportant views is enabled
    // Indicate whether trigger fill request on unimportant views is enabled
    private boolean mIsTriggerFillRequestOnUnimportantViewEnabled = false;
    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
    // A set containing all non-autofillable ime actions passed by flag
    private Set<String> mNonAutofillableImeActionIdSet = new ArraySet<>();
    private Set<String> mNonAutofillableImeActionIdSet = new ArraySet<>();


@@ -855,6 +861,12 @@ public final class AutofillManager {
        mIsTriggerFillRequestOnUnimportantViewEnabled =
        mIsTriggerFillRequestOnUnimportantViewEnabled =
            AutofillFeatureFlags.isTriggerFillRequestOnUnimportantViewEnabled();
            AutofillFeatureFlags.isTriggerFillRequestOnUnimportantViewEnabled();


        mIsTriggerFillRequestOnFilteredImportantViewsEnabled =
            AutofillFeatureFlags.isTriggerFillRequestOnFilteredImportantViewsEnabled();

        mShouldEnableAutofillOnAllViewTypes =
            AutofillFeatureFlags.shouldEnableAutofillOnAllViewTypes();

        mNonAutofillableImeActionIdSet =
        mNonAutofillableImeActionIdSet =
            AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();
            AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();


@@ -865,14 +877,39 @@ public final class AutofillManager {
        mIsPackageFullyDeniedForAutofillForUnimportantView =
        mIsPackageFullyDeniedForAutofillForUnimportantView =
            isPackageFullyDeniedForAutofillForUnimportantView(denyListString, packageName);
            isPackageFullyDeniedForAutofillForUnimportantView(denyListString, packageName);


        if (!mIsPackageFullyDeniedForAutofillForUnimportantView) {
            mIsPackagePartiallyDeniedForAutofillForUnimportantView =
            mIsPackagePartiallyDeniedForAutofillForUnimportantView =
                isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
                isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
        }


        if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
        if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
            setDeniedActivitySetWithDenyList(denyListString, packageName);
            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(
    private boolean isPackageFullyDeniedForAutofillForUnimportantView(
            @NonNull String denyListString, @NonNull String packageName) {
            @NonNull String denyListString, @NonNull String packageName) {
        // If "PackageName:;" is in the string, then it means the package name is in denylist
        // If "PackageName:;" is in the string, then it means the package name is in denylist
@@ -957,17 +994,23 @@ public final class AutofillManager {
     *
     *
     * @hide
     * @hide
     */
     */
    public final boolean isMatchingAutofillableHeuristics(@NonNull View view) {
    public final boolean isMatchingAutofillableHeuristicsForNotImportantViews(@NonNull View view) {
        if (!mIsTriggerFillRequestOnUnimportantViewEnabled) {
        if (!mIsTriggerFillRequestOnUnimportantViewEnabled) {
            return false;
            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) {
        if (view instanceof EditText) {
            final int actionId = ((EditText) view).getImeOptions();
            return isPassingImeActionCheck((EditText) view);
            if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
                return false;
            }
            return true;
        }
        }

        if (view instanceof CheckBox
        if (view instanceof CheckBox
            || view instanceof Spinner
            || view instanceof Spinner
            || view instanceof DatePicker
            || view instanceof DatePicker
@@ -975,7 +1018,8 @@ public final class AutofillManager {
            || view instanceof RadioGroup) {
            || view instanceof RadioGroup) {
            return true;
            return true;
        }
        }
        return false;

        return mShouldEnableAutofillOnAllViewTypes;
    }
    }