Merge "Autofill For All Apps - Add in autofill allowlist" into udc-dev
This commit is contained in:
@@ -149,6 +149,15 @@ public class AutofillFeatureFlags {
|
||||
public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW =
|
||||
"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
|
||||
*/
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user