summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/autofill/AutofillFeatureFlags.java20
-rw-r--r--core/java/android/view/autofill/AutofillManager.java138
2 files changed, 117 insertions, 41 deletions
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
index e267a7f1e248..e51eff42fed5 100644
--- a/core/java/android/view/autofill/AutofillFeatureFlags.java
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -150,6 +150,15 @@ public class AutofillFeatureFlags {
"package_deny_list_for_unimportant_view";
/**
+ * Sets the list of activities and packages allowed for autofill. The format is same with
+ * {@link #DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW}
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_PACKAGE_AND_ACTIVITY_ALLOWLIST_FOR_TRIGGERING_FILL_REQUEST =
+ "package_and_activity_allowlist_for_triggering_fill_request";
+
+ /**
* Whether the heuristics check for view is enabled
*/
public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW =
@@ -183,6 +192,7 @@ public class AutofillFeatureFlags {
*/
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 //
@@ -378,6 +388,16 @@ public class AutofillFeatureFlags {
DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW, "");
}
+ /**
+ * Get autofill allowlist from flag
+ *
+ * @hide
+ */
+ public static String getAllowlistStringFromFlag() {
+ return DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_AUTOFILL,
+ DEVICE_CONFIG_PACKAGE_AND_ACTIVITY_ALLOWLIST_FOR_TRIGGERING_FILL_REQUEST, "");
+ }
// START AUTOFILL PCC CLASSIFICATION FUNCTIONS
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 781a4b63f889..37f66facf3d7 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -694,7 +694,18 @@ public final class AutofillManager {
private boolean mIsPackagePartiallyDeniedForAutofill = false;
// A deny set read from device config
- private Set<String> mDeniedActivitiySet = new ArraySet<>();
+ private Set<String> mDeniedActivitySet = new ArraySet<>();
+
+ // If a package is fully allowed, all views in package will skip the heuristic check
+ private boolean mIsPackageFullyAllowedForAutofill = false;
+
+ // If a package is partially denied, autofill manager will check whether
+ // current activity is in allowed activity set. If it's allowed activity, then autofill manager
+ // will skip the heuristic check
+ private boolean mIsPackagePartiallyAllowedForAutofill = false;
+
+ // An allowed activity set read from device config
+ private Set<String> mAllowedActivitySet = new ArraySet<>();
// Indicates whether called the showAutofillDialog() method.
private boolean mShowAutofillDialogCalled = false;
@@ -873,19 +884,34 @@ public final class AutofillManager {
AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();
final String denyListString = AutofillFeatureFlags.getDenylistStringFromFlag();
+ final String allowlistString = AutofillFeatureFlags.getAllowlistStringFromFlag();
final String packageName = mContext.getPackageName();
mIsPackageFullyDeniedForAutofill =
- isPackageFullyDeniedForAutofill(denyListString, packageName);
+ isPackageFullyAllowedOrDeniedForAutofill(denyListString, packageName);
+
+ mIsPackageFullyAllowedForAutofill =
+ isPackageFullyAllowedOrDeniedForAutofill(allowlistString, packageName);
if (!mIsPackageFullyDeniedForAutofill) {
mIsPackagePartiallyDeniedForAutofill =
- isPackagePartiallyDeniedForAutofill(denyListString, packageName);
+ isPackagePartiallyDeniedOrAllowedForAutofill(denyListString, packageName);
+ }
+
+ if (!mIsPackageFullyAllowedForAutofill) {
+ mIsPackagePartiallyAllowedForAutofill =
+ isPackagePartiallyDeniedOrAllowedForAutofill(allowlistString, packageName);
}
if (mIsPackagePartiallyDeniedForAutofill) {
- setDeniedActivitySetWithDenyList(denyListString, packageName);
+ mDeniedActivitySet = getDeniedOrAllowedActivitySetFromString(
+ denyListString, packageName);
+ }
+
+ if (mIsPackagePartiallyAllowedForAutofill) {
+ mAllowedActivitySet = getDeniedOrAllowedActivitySetFromString(
+ allowlistString, packageName);
}
}
@@ -921,59 +947,59 @@ public final class AutofillManager {
return true;
}
- private boolean isPackageFullyDeniedForAutofill(
- @NonNull String denyListString, @NonNull String packageName) {
- // 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
- // denied for autofill
- return denyListString.indexOf(packageName + ":;") != -1;
+ private boolean isPackageFullyAllowedOrDeniedForAutofill(
+ @NonNull String listString, @NonNull String packageName) {
+ // If "PackageName:;" is in the string, then it the package is fully denied or allowed for
+ // autofill, depending on which string is passed to this function
+ return listString.indexOf(packageName + ":;") != -1;
}
- private boolean isPackagePartiallyDeniedForAutofill(
- @NonNull String denyListString, @NonNull String packageName) {
- // 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 partially denied for autofill
- return denyListString.indexOf(packageName + ":") != -1;
+ private boolean isPackagePartiallyDeniedOrAllowedForAutofill(
+ @NonNull String listString, @NonNull String packageName) {
+ // If "PackageName:" is in string when "PackageName:;" is not, then it means there are
+ // specific activities to be allowed or denied. So the package is partially allowed or
+ // denied for autofill.
+ return listString.indexOf(packageName + ":") != -1;
}
/**
- * Get the denied activitiy names under specified package from denylist and set it in field
- * mDeniedActivitiySet
+ * Get the denied or allowed activitiy names under specified package from the list string and
+ * set it in fields accordingly
*
- * If using parameter as the example below, the denied activity set would be set to
- * Set{Activity1,Activity2}.
+ * For example, if the package name is Package1, and the string is
+ * "Package1:Activity1,Activity2;", then the extracted activity set would be
+ * {Activity1, Activity2}
*
- * @param denyListString Denylist that is got from device config. For example,
+ * @param listString Denylist that is got from device config. For example,
* "Package1:Activity1,Activity2;Package2:;"
- * @param packageName Specify to extract activities under which package.For example,
- * "Package1:;"
+ * @param packageName Specify which package to extract.For example, "Package1"
+ *
+ * @return the extracted activity set, For example, {Activity1, Activity2}
*/
- private void setDeniedActivitySetWithDenyList(
- @NonNull String denyListString, @NonNull String packageName) {
+ private Set<String> getDeniedOrAllowedActivitySetFromString(
+ @NonNull String listString, @NonNull String packageName) {
// 1. Get the index of where the Package name starts
- final int packageInStringIndex = denyListString.indexOf(packageName + ":");
+ final int packageInStringIndex = listString.indexOf(packageName + ":");
// 2. Get the ";" index after this index of package
- final int firstNextSemicolonIndex = denyListString.indexOf(";", packageInStringIndex);
+ final int firstNextSemicolonIndex = listString.indexOf(";", packageInStringIndex);
// 3. Get the activity names substring between the indexes
final int activityStringStartIndex = packageInStringIndex + packageName.length() + 1;
+
if (activityStringStartIndex >= firstNextSemicolonIndex) {
- Log.e(TAG, "Failed to get denied activity names from denylist because it's wrongly "
+ Log.e(TAG, "Failed to get denied activity names from list because it's wrongly "
+ "formatted");
- return;
+ return new ArraySet<>();
}
final String activitySubstring =
- denyListString.substring(activityStringStartIndex, firstNextSemicolonIndex);
+ listString.substring(activityStringStartIndex, firstNextSemicolonIndex);
// 4. Split the activity name substring
final String[] activityStringArray = activitySubstring.split(",");
- // 5. Set the denied activity set
- mDeniedActivitiySet = new ArraySet<>(Arrays.asList(activityStringArray));
-
- return;
+ // 5. return the extracted activities in a set
+ return new ArraySet<>(Arrays.asList(activityStringArray));
}
/**
@@ -992,7 +1018,32 @@ public final class AutofillManager {
return false;
}
final ComponentName clientActivity = client.autofillClientGetComponentName();
- if (mDeniedActivitiySet.contains(clientActivity.flattenToShortString())) {
+ if (mDeniedActivitySet.contains(clientActivity.flattenToShortString())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check whether current activity is allowlisted for autofill.
+ *
+ * If it is, the view in current activity will bypass heuristic check when checking whether it's
+ * autofillable
+ *
+ * @hide
+ */
+ public boolean isActivityAllowedForAutofill() {
+ if (mIsPackageFullyAllowedForAutofill) {
+ return true;
+ }
+ if (mIsPackagePartiallyAllowedForAutofill) {
+ final AutofillClient client = getClient();
+ if (client == null) {
+ return false;
+ }
+ final ComponentName clientActivity = client.autofillClientGetComponentName();
+ if (mAllowedActivitySet.contains(clientActivity.flattenToShortString())) {
return true;
}
}
@@ -1009,17 +1060,22 @@ public final class AutofillManager {
* @hide
*/
public boolean isAutofillable(View view) {
- if (isActivityDeniedForAutofill()) {
- Log.d(TAG, "view is not autofillable - activity denied for autofill");
- return false;
- }
-
// Duplicate the autofill type check here because ViewGroup will call this function to
// decide whether to include view in assist structure.
// Also keep the autofill type check inside View#IsAutofillable() to serve as an early out
// or if other functions need to call it.
if (view.getAutofillType() == View.AUTOFILL_TYPE_NONE) return false;
+ if (isActivityDeniedForAutofill()) {
+ Log.d(TAG, "view is not autofillable - activity denied for autofill");
+ return false;
+ }
+
+ if (isActivityAllowedForAutofill()) {
+ Log.d(TAG, "view is autofillable - activity allowed for autofill");
+ return true;
+ }
+
if (view instanceof EditText) {
return isPassingImeActionCheck((EditText) view);
}
@@ -1037,7 +1093,7 @@ public final class AutofillManager {
|| view instanceof RadioGroup) {
return true;
}
-
+ Log.d(TAG, "view is not autofillable - not important and filtered by view type check");
return false;
}