Merge "Adding experiment flags for optimization part of autofill for all apps" into udc-dev
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
mIsPackagePartiallyDeniedForAutofillForUnimportantView =
|
if (!mIsPackageFullyDeniedForAutofillForUnimportantView) {
|
||||||
isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
|
mIsPackagePartiallyDeniedForAutofillForUnimportantView =
|
||||||
|
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,25 +994,32 @@ 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
|
||||||
|| view instanceof TimePicker
|
|| view instanceof TimePicker
|
||||||
|| view instanceof RadioGroup) {
|
|| view instanceof RadioGroup) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return mShouldEnableAutofillOnAllViewTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user