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 =
|
public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW =
|
||||||
"package_deny_list_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
|
* 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 =
|
public static final String DEVICE_CONFIG_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES =
|
||||||
"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 //
|
||||||
|
|
||||||
|
|
||||||
@@ -378,6 +388,16 @@ public class AutofillFeatureFlags {
|
|||||||
DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW, "");
|
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
|
// START AUTOFILL PCC CLASSIFICATION FUNCTIONS
|
||||||
|
|
||||||
|
|||||||
@@ -694,7 +694,18 @@ public final class AutofillManager {
|
|||||||
private boolean mIsPackagePartiallyDeniedForAutofill = 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> 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.
|
// Indicates whether called the showAutofillDialog() method.
|
||||||
private boolean mShowAutofillDialogCalled = false;
|
private boolean mShowAutofillDialogCalled = false;
|
||||||
@@ -873,19 +884,34 @@ public final class AutofillManager {
|
|||||||
AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();
|
AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();
|
||||||
|
|
||||||
final String denyListString = AutofillFeatureFlags.getDenylistStringFromFlag();
|
final String denyListString = AutofillFeatureFlags.getDenylistStringFromFlag();
|
||||||
|
final String allowlistString = AutofillFeatureFlags.getAllowlistStringFromFlag();
|
||||||
|
|
||||||
final String packageName = mContext.getPackageName();
|
final String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
mIsPackageFullyDeniedForAutofill =
|
mIsPackageFullyDeniedForAutofill =
|
||||||
isPackageFullyDeniedForAutofill(denyListString, packageName);
|
isPackageFullyAllowedOrDeniedForAutofill(denyListString, packageName);
|
||||||
|
|
||||||
|
mIsPackageFullyAllowedForAutofill =
|
||||||
|
isPackageFullyAllowedOrDeniedForAutofill(allowlistString, packageName);
|
||||||
|
|
||||||
if (!mIsPackageFullyDeniedForAutofill) {
|
if (!mIsPackageFullyDeniedForAutofill) {
|
||||||
mIsPackagePartiallyDeniedForAutofill =
|
mIsPackagePartiallyDeniedForAutofill =
|
||||||
isPackagePartiallyDeniedForAutofill(denyListString, packageName);
|
isPackagePartiallyDeniedOrAllowedForAutofill(denyListString, packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mIsPackageFullyAllowedForAutofill) {
|
||||||
|
mIsPackagePartiallyAllowedForAutofill =
|
||||||
|
isPackagePartiallyDeniedOrAllowedForAutofill(allowlistString, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsPackagePartiallyDeniedForAutofill) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPackageFullyDeniedForAutofill(
|
private boolean isPackageFullyAllowedOrDeniedForAutofill(
|
||||||
@NonNull String denyListString, @NonNull String packageName) {
|
@NonNull String listString, @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 the package is fully denied or allowed for
|
||||||
// and there are no activities specified under it. That means the package is fully
|
// autofill, depending on which string is passed to this function
|
||||||
// denied for autofill
|
return listString.indexOf(packageName + ":;") != -1;
|
||||||
return denyListString.indexOf(packageName + ":;") != -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPackagePartiallyDeniedForAutofill(
|
private boolean isPackagePartiallyDeniedOrAllowedForAutofill(
|
||||||
@NonNull String denyListString, @NonNull String packageName) {
|
@NonNull String listString, @NonNull String packageName) {
|
||||||
// This check happens after checking package is not fully denied. If "PackageName:" instead
|
// If "PackageName:" is in string when "PackageName:;" is not, then it means there are
|
||||||
// is in denylist, then it means there are specific activities to be denied. So the package
|
// specific activities to be allowed or denied. So the package is partially allowed or
|
||||||
// is partially denied for autofill
|
// denied for autofill.
|
||||||
return denyListString.indexOf(packageName + ":") != -1;
|
return listString.indexOf(packageName + ":") != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the denied activitiy names under specified package from denylist and set it in field
|
* Get the denied or allowed activitiy names under specified package from the list string and
|
||||||
* mDeniedActivitiySet
|
* set it in fields accordingly
|
||||||
*
|
*
|
||||||
* If using parameter as the example below, the denied activity set would be set to
|
* For example, if the package name is Package1, and the string is
|
||||||
* Set{Activity1,Activity2}.
|
* "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:;"
|
* "Package1:Activity1,Activity2;Package2:;"
|
||||||
* @param packageName Specify to extract activities under which package.For example,
|
* @param packageName Specify which package to extract.For example, "Package1"
|
||||||
* "Package1:;"
|
*
|
||||||
|
* @return the extracted activity set, For example, {Activity1, Activity2}
|
||||||
*/
|
*/
|
||||||
private void setDeniedActivitySetWithDenyList(
|
private Set<String> getDeniedOrAllowedActivitySetFromString(
|
||||||
@NonNull String denyListString, @NonNull String packageName) {
|
@NonNull String listString, @NonNull String packageName) {
|
||||||
// 1. Get the index of where the Package name starts
|
// 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
|
// 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
|
// 3. Get the activity names substring between the indexes
|
||||||
final int activityStringStartIndex = packageInStringIndex + packageName.length() + 1;
|
final int activityStringStartIndex = packageInStringIndex + packageName.length() + 1;
|
||||||
|
|
||||||
if (activityStringStartIndex >= firstNextSemicolonIndex) {
|
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");
|
+ "formatted");
|
||||||
return;
|
return new ArraySet<>();
|
||||||
}
|
}
|
||||||
final String activitySubstring =
|
final String activitySubstring =
|
||||||
denyListString.substring(activityStringStartIndex, firstNextSemicolonIndex);
|
listString.substring(activityStringStartIndex, firstNextSemicolonIndex);
|
||||||
|
|
||||||
// 4. Split the activity name substring
|
// 4. Split the activity name substring
|
||||||
final String[] activityStringArray = activitySubstring.split(",");
|
final String[] activityStringArray = activitySubstring.split(",");
|
||||||
|
|
||||||
// 5. Set the denied activity set
|
// 5. return the extracted activities in a set
|
||||||
mDeniedActivitiySet = new ArraySet<>(Arrays.asList(activityStringArray));
|
return new ArraySet<>(Arrays.asList(activityStringArray));
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -992,7 +1018,32 @@ public final class AutofillManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final ComponentName clientActivity = client.autofillClientGetComponentName();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1009,17 +1060,22 @@ public final class AutofillManager {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public boolean isAutofillable(View view) {
|
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
|
// Duplicate the autofill type check here because ViewGroup will call this function to
|
||||||
// decide whether to include view in assist structure.
|
// decide whether to include view in assist structure.
|
||||||
// Also keep the autofill type check inside View#IsAutofillable() to serve as an early out
|
// Also keep the autofill type check inside View#IsAutofillable() to serve as an early out
|
||||||
// or if other functions need to call it.
|
// or if other functions need to call it.
|
||||||
if (view.getAutofillType() == View.AUTOFILL_TYPE_NONE) return false;
|
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) {
|
if (view instanceof EditText) {
|
||||||
return isPassingImeActionCheck((EditText) view);
|
return isPassingImeActionCheck((EditText) view);
|
||||||
}
|
}
|
||||||
@@ -1037,7 +1093,7 @@ public final class AutofillManager {
|
|||||||
|| view instanceof RadioGroup) {
|
|| view instanceof RadioGroup) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "view is not autofillable - not important and filtered by view type check");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user