Merge "Autofill For All Apps - refactor to have important and not impotant views call the same isAutofillable() function in AutofillManager" into udc-dev
This commit is contained in:
@@ -163,7 +163,6 @@ 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;
|
||||||
@@ -10347,24 +10346,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether current activity / package is in denylist.If it's in the denylist,
|
* Check whether current activity / package is in autofill denylist.
|
||||||
* then the views marked as not important for autofill are not eligible for autofill.
|
*
|
||||||
|
* Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
|
||||||
|
* assist structure
|
||||||
*/
|
*/
|
||||||
final boolean isActivityDeniedForAutofillForUnimportantView() {
|
final boolean isActivityDeniedForAutofillForUnimportantView() {
|
||||||
final AutofillManager afm = getAutofillManager();
|
final AutofillManager afm = getAutofillManager();
|
||||||
// keep behavior same with denylist feature not enabled
|
if (afm == null) return false;
|
||||||
if (afm == null) return true;
|
return afm.isActivityDeniedForAutofill();
|
||||||
return afm.isActivityDeniedForAutofillForUnimportantView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether current view matches autofillable heuristics
|
* Check whether current view matches autofillable heuristics
|
||||||
|
*
|
||||||
|
* Called by viewGroup#populateChildrenForAutofill() to determine whether to include view in
|
||||||
|
* assist structure
|
||||||
*/
|
*/
|
||||||
final boolean isMatchingAutofillableHeuristics() {
|
final boolean isMatchingAutofillableHeuristics() {
|
||||||
final AutofillManager afm = getAutofillManager();
|
final AutofillManager afm = getAutofillManager();
|
||||||
// keep default behavior
|
|
||||||
if (afm == null) return false;
|
if (afm == null) return false;
|
||||||
return afm.isMatchingAutofillableHeuristicsForNotImportantViews(this);
|
// check the flag to see if trigger fill request on not important views is enabled
|
||||||
|
return afm.isTriggerFillRequestOnUnimportantViewEnabled()
|
||||||
|
? afm.isAutofillable(this) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAutofillable() {
|
private boolean isAutofillable() {
|
||||||
@@ -10380,39 +10384,26 @@ 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
|
// Check whether view is not part of an activity. If it's not, return false.
|
||||||
// heuristic check, also check augmented autofill in case augmented autofill is enabled
|
if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
|
||||||
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isImportantForAutofill()) {
|
// If view is important and filter important view flag is turned on, or view is not
|
||||||
// If view matches heuristics and is not denied, it will be treated same as view that's
|
// important and trigger fill request on not important view flag is turned on, then use
|
||||||
// important for autofill
|
// AutofillManager.isAutofillable() to decide whether view is autofillable instead.
|
||||||
if (afm.isMatchingAutofillableHeuristicsForNotImportantViews(this)
|
if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
|
||||||
&& !afm.isActivityDeniedForAutofillForUnimportantView()) {
|
|| (!isImportantForAutofill()
|
||||||
return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
|
&& afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
|
||||||
}
|
return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
|
||||||
// View is not important for "regular" autofill, so we must check if Augmented Autofill
|
|
||||||
// is enabled for the activity
|
|
||||||
if (!notifyAugmentedAutofillIfNeeded(afm)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
|
// If the previous condition is not met, fall back to the previous way to trigger fill
|
||||||
|
// request based on autofill importance instead.
|
||||||
|
return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide **/
|
private boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
|
||||||
public boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
|
|
||||||
final AutofillOptions options = mContext.getAutofillOptions();
|
final AutofillOptions options = mContext.getAutofillOptions();
|
||||||
if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
|
if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -365,7 +365,10 @@ public class AutofillFeatureFlags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get denylist string from flag
|
* Get denylist string from flag.
|
||||||
|
*
|
||||||
|
* Note: This denylist works both on important view and not important views. The flag used here
|
||||||
|
* is legacy flag which will be replaced with soon.
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -687,11 +687,11 @@ public final class AutofillManager {
|
|||||||
|
|
||||||
// If a package is fully denied, then all views that marked as not
|
// If a package is fully denied, then all views that marked as not
|
||||||
// important for autofill will not trigger fill request
|
// important for autofill will not trigger fill request
|
||||||
private boolean mIsPackageFullyDeniedForAutofillForUnimportantView = false;
|
private boolean mIsPackageFullyDeniedForAutofill = false;
|
||||||
|
|
||||||
// If a package is partially denied, autofill manager will check whether
|
// If a package is partially denied, autofill manager will check whether
|
||||||
// current activity is in deny set to decide whether to trigger fill request
|
// current activity is in deny set to decide whether to trigger fill request
|
||||||
private boolean mIsPackagePartiallyDeniedForAutofillForUnimportantView = false;
|
private boolean mIsPackagePartiallyDeniedForAutofill = false;
|
||||||
|
|
||||||
// A deny set read from device config
|
// A deny set read from device config
|
||||||
private Set<String> mDeniedActivitiySet = new ArraySet<>();
|
private Set<String> mDeniedActivitiySet = new ArraySet<>();
|
||||||
@@ -876,15 +876,15 @@ public final class AutofillManager {
|
|||||||
|
|
||||||
final String packageName = mContext.getPackageName();
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
mIsPackageFullyDeniedForAutofillForUnimportantView =
|
mIsPackageFullyDeniedForAutofill =
|
||||||
isPackageFullyDeniedForAutofillForUnimportantView(denyListString, packageName);
|
isPackageFullyDeniedForAutofill(denyListString, packageName);
|
||||||
|
|
||||||
if (!mIsPackageFullyDeniedForAutofillForUnimportantView) {
|
if (!mIsPackageFullyDeniedForAutofill) {
|
||||||
mIsPackagePartiallyDeniedForAutofillForUnimportantView =
|
mIsPackagePartiallyDeniedForAutofill =
|
||||||
isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
|
isPackagePartiallyDeniedForAutofill(denyListString, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
|
if (mIsPackagePartiallyDeniedForAutofill) {
|
||||||
setDeniedActivitySetWithDenyList(denyListString, packageName);
|
setDeniedActivitySetWithDenyList(denyListString, packageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -898,6 +898,15 @@ public final class AutofillManager {
|
|||||||
return mIsTriggerFillRequestOnFilteredImportantViewsEnabled;
|
return mIsTriggerFillRequestOnFilteredImportantViewsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to trigger fill request on not important views that passes heuristic check
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isTriggerFillRequestOnUnimportantViewEnabled() {
|
||||||
|
return mIsTriggerFillRequestOnUnimportantViewEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether view passes the imeAction check
|
* Whether view passes the imeAction check
|
||||||
*
|
*
|
||||||
@@ -906,13 +915,13 @@ public final class AutofillManager {
|
|||||||
public boolean isPassingImeActionCheck(EditText editText) {
|
public boolean isPassingImeActionCheck(EditText editText) {
|
||||||
final int actionId = editText.getImeOptions();
|
final int actionId = editText.getImeOptions();
|
||||||
if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
|
if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
|
||||||
// TODO: add a log to indicate what has filtered out the view
|
Log.d(TAG, "view not autofillable - not passing ime action check");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPackageFullyDeniedForAutofillForUnimportantView(
|
private boolean isPackageFullyDeniedForAutofill(
|
||||||
@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
|
||||||
// and there are no activities specified under it. That means the package is fully
|
// and there are no activities specified under it. That means the package is fully
|
||||||
@@ -920,7 +929,7 @@ public final class AutofillManager {
|
|||||||
return denyListString.indexOf(packageName + ":;") != -1;
|
return denyListString.indexOf(packageName + ":;") != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPackagePartiallyDeniedForAutofillForUnimportantView(
|
private boolean isPackagePartiallyDeniedForAutofill(
|
||||||
@NonNull String denyListString, @NonNull String packageName) {
|
@NonNull String denyListString, @NonNull String packageName) {
|
||||||
// This check happens after checking package is not fully denied. If "PackageName:" instead
|
// This check happens after checking package is not fully denied. If "PackageName:" instead
|
||||||
// is in denylist, then it means there are specific activities to be denied. So the package
|
// is in denylist, then it means there are specific activities to be denied. So the package
|
||||||
@@ -968,17 +977,16 @@ public final class AutofillManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether autofill is denied for current activity or package. Used when a view is marked
|
* Check whether autofill is denied for current activity or package. If current activity or
|
||||||
* as not important for autofill, if current activity or package is denied, then the view won't
|
* package is denied, then the view won't trigger fill request.
|
||||||
* trigger fill request.
|
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final boolean isActivityDeniedForAutofillForUnimportantView() {
|
public boolean isActivityDeniedForAutofill() {
|
||||||
if (mIsPackageFullyDeniedForAutofillForUnimportantView) {
|
if (mIsPackageFullyDeniedForAutofill) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
|
if (mIsPackagePartiallyDeniedForAutofill) {
|
||||||
final AutofillClient client = getClient();
|
final AutofillClient client = getClient();
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -992,27 +1000,36 @@ public final class AutofillManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether view matches autofill-able heuristics
|
* Check heuristics and other rules to determine if view is autofillable
|
||||||
|
*
|
||||||
|
* Note: this function should be only called only when autofill for all apps is turned on. The
|
||||||
|
* calling method needs to check the corresponding flag to make sure that before calling into
|
||||||
|
* this function.
|
||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final boolean isMatchingAutofillableHeuristicsForNotImportantViews(@NonNull View view) {
|
public boolean isAutofillable(View view) {
|
||||||
if (!mIsTriggerFillRequestOnUnimportantViewEnabled) {
|
if (isActivityDeniedForAutofill()) {
|
||||||
|
Log.d(TAG, "view is not autofillable - activity denied for autofill");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove the autofill type check when this function is applied on both important and
|
// Duplicate the autofill type check here because ViewGroup will call this function to
|
||||||
// not important views.
|
// decide whether to include view in assist structure.
|
||||||
// This check is needed here because once the view type check is lifted, addiditional
|
// Also keep the autofill type check inside View#IsAutofillable() to serve as an early out
|
||||||
// unimportant views will be added to the assist structure which may cuase system health
|
// or if other functions need to call it.
|
||||||
// regression (viewGroup#populateChidlrenForAutofill() calls this function to decide whether
|
|
||||||
// to include child view)
|
|
||||||
if (view.getAutofillType() == View.AUTOFILL_TYPE_NONE) return false;
|
if (view.getAutofillType() == View.AUTOFILL_TYPE_NONE) return false;
|
||||||
|
|
||||||
if (view instanceof EditText) {
|
if (view instanceof EditText) {
|
||||||
return isPassingImeActionCheck((EditText) view);
|
return isPassingImeActionCheck((EditText) view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip view type check if view is important for autofill or
|
||||||
|
// shouldEnableAutofillOnAllViewTypes flag is turned on
|
||||||
|
if (view.isImportantForAutofill() || mShouldEnableAutofillOnAllViewTypes) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (view instanceof CheckBox
|
if (view instanceof CheckBox
|
||||||
|| view instanceof Spinner
|
|| view instanceof Spinner
|
||||||
|| view instanceof DatePicker
|
|| view instanceof DatePicker
|
||||||
@@ -1021,10 +1038,9 @@ public final class AutofillManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mShouldEnableAutofillOnAllViewTypes;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user