Merge "Initial implementation of AutofillManager.setAugmentedAutofillWhitelist()"
This commit is contained in:
committed by
Android (Google) Code Review
commit
02aca1058f
@@ -369,6 +369,11 @@ public final class AutofillManager {
|
||||
public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES =
|
||||
"smart_suggestion_supported_modes";
|
||||
|
||||
/** @hide */
|
||||
public static final int RESULT_OK = 0;
|
||||
/** @hide */
|
||||
public static final int RESULT_CODE_NOT_SERVICE = -1;
|
||||
|
||||
/**
|
||||
* Makes an authentication id from a request id and a dataset id.
|
||||
*
|
||||
@@ -1789,7 +1794,11 @@ public final class AutofillManager {
|
||||
@Deprecated
|
||||
public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
|
||||
@Nullable List<ComponentName> activities) {
|
||||
// TODO(b/123100824): implement
|
||||
setAugmentedAutofillWhitelist(toSet(packages), toSet(activities));
|
||||
}
|
||||
|
||||
private <T> ArraySet<T> toSet(@Nullable List<T> set) {
|
||||
return set == null ? null : new ArraySet<T>(set);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1814,7 +1823,32 @@ public final class AutofillManager {
|
||||
@TestApi
|
||||
public void setAugmentedAutofillWhitelist(@Nullable Set<String> packages,
|
||||
@Nullable Set<ComponentName> activities) {
|
||||
// TODO(b/123100824): implement
|
||||
if (!hasAutofillFeature()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
|
||||
final int resultCode;
|
||||
try {
|
||||
mService.setAugmentedAutofillWhitelist(toList(packages), toList(activities),
|
||||
resultReceiver);
|
||||
resultCode = resultReceiver.getIntResult();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
switch (resultCode) {
|
||||
case RESULT_OK:
|
||||
return;
|
||||
case RESULT_CODE_NOT_SERVICE:
|
||||
throw new SecurityException("caller is not user's Augmented Autofill Service");
|
||||
default:
|
||||
Log.wtf(TAG, "setAugmentedAutofillWhitelist(): received invalid result: "
|
||||
+ resultCode);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> ArrayList<T> toList(@Nullable Set<T> set) {
|
||||
return set == null ? null : new ArrayList<T>(set);
|
||||
}
|
||||
|
||||
private void requestShowFillUi(int sessionId, AutofillId id, int width, int height,
|
||||
|
||||
@@ -63,4 +63,6 @@ oneway interface IAutoFillManager {
|
||||
void getAutofillServiceComponentName(in IResultReceiver result);
|
||||
void getAvailableFieldClassificationAlgorithms(in IResultReceiver result);
|
||||
void getDefaultFieldClassificationAlgorithm(in IResultReceiver result);
|
||||
void setAugmentedAutofillWhitelist(in List<String> packages, in List<ComponentName> activities,
|
||||
in IResultReceiver result);
|
||||
}
|
||||
|
||||
@@ -1025,6 +1025,29 @@ public final class AutofillManagerService
|
||||
send(receiver, algorithm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
|
||||
@Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)
|
||||
throws RemoteException {
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
|
||||
boolean ok;
|
||||
synchronized (mLock) {
|
||||
final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
|
||||
if (service != null) {
|
||||
ok = service.setAugmentedAutofillWhitelistLocked(packages, activities,
|
||||
getCallingUid());
|
||||
} else {
|
||||
if (sVerbose) {
|
||||
Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " + userId);
|
||||
}
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
send(receiver,
|
||||
ok ? AutofillManager.RESULT_OK : AutofillManager.RESULT_CODE_NOT_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver)
|
||||
throws RemoteException {
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
@@ -58,6 +59,7 @@ import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.DebugUtils;
|
||||
import android.util.LocalLog;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TimeUtils;
|
||||
@@ -165,6 +167,16 @@ final class AutofillManagerServiceImpl
|
||||
@Nullable
|
||||
private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private ServiceInfo mRemoteAugmentedAutofillServiceInfo;
|
||||
|
||||
/**
|
||||
* List of packages that are whitelisted to be trigger augmented autofill.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final ArraySet<String> mWhitelistedAugmentAutofillPackages = new ArraySet<>();
|
||||
|
||||
AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
|
||||
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
|
||||
AutofillCompatState autofillCompatState,
|
||||
@@ -844,10 +856,11 @@ final class AutofillManagerServiceImpl
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean isCalledByServiceLocked(String methodName, int callingUid) {
|
||||
if (getServiceUidLocked() != callingUid) {
|
||||
private boolean isCalledByServiceLocked(@NonNull String methodName, int callingUid) {
|
||||
final int serviceUid = getServiceUidLocked();
|
||||
if (serviceUid != callingUid) {
|
||||
Slog.w(TAG, methodName + "() called by UID " + callingUid
|
||||
+ ", but service UID is " + getServiceUidLocked());
|
||||
+ ", but service UID is " + serviceUid);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -886,6 +899,19 @@ final class AutofillManagerServiceImpl
|
||||
pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
|
||||
mRemoteAugmentedAutofillService.dump(prefix2, pw);
|
||||
}
|
||||
if (mRemoteAugmentedAutofillServiceInfo != null) {
|
||||
pw.print(prefix); pw.print("RemoteAugmentedAutofillServiceInfo: ");
|
||||
pw.println(mRemoteAugmentedAutofillServiceInfo);
|
||||
}
|
||||
|
||||
final int whitelistSize = mWhitelistedAugmentAutofillPackages.size();
|
||||
pw.print(prefix); pw.print("Packages whitelisted for augmented autofill: ");
|
||||
pw.println(whitelistSize);
|
||||
for (int i = 0; i < whitelistSize; i++) {
|
||||
final String whitelistedPkg = mWhitelistedAugmentAutofillPackages.valueAt(i);
|
||||
pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
|
||||
}
|
||||
|
||||
pw.print(prefix); pw.print("Field classification enabled: ");
|
||||
pw.println(isFieldClassificationEnabledLocked());
|
||||
pw.print(prefix); pw.print("Compat pkgs: ");
|
||||
@@ -1037,9 +1063,13 @@ final class AutofillManagerServiceImpl
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final ComponentName componentName = RemoteAugmentedAutofillService.getComponentName(
|
||||
serviceName, mUserId, mAugmentedAutofillResolver.isTemporary(mUserId));
|
||||
if (componentName == null) return null;
|
||||
final Pair<ServiceInfo, ComponentName> pair = RemoteAugmentedAutofillService
|
||||
.getComponentName(
|
||||
serviceName, mUserId, mAugmentedAutofillResolver.isTemporary(mUserId));
|
||||
if (pair == null) return null;
|
||||
|
||||
mRemoteAugmentedAutofillServiceInfo = pair.first;
|
||||
final ComponentName componentName = pair.second;
|
||||
if (sVerbose) {
|
||||
Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
|
||||
}
|
||||
@@ -1067,9 +1097,87 @@ final class AutofillManagerServiceImpl
|
||||
private void updateRemoteAugmentedAutofillService(@Nullable String serviceName) {
|
||||
if (serviceName == null) {
|
||||
if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
|
||||
if (mRemoteAugmentedAutofillService != null) {
|
||||
mRemoteAugmentedAutofillService.destroy();
|
||||
mRemoteAugmentedAutofillService = null;
|
||||
synchronized (mLock) {
|
||||
if (mRemoteAugmentedAutofillService != null) {
|
||||
mRemoteAugmentedAutofillService.destroy();
|
||||
mRemoteAugmentedAutofillService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets which packages and activities can trigger augmented autofill.
|
||||
*
|
||||
* @return whether caller UID is the augmented autofill service for the user
|
||||
*/
|
||||
boolean setAugmentedAutofillWhitelistLocked(List<String> packages,
|
||||
List<ComponentName> activities, int callingUid) {
|
||||
|
||||
if (!isCalledByAugmentedAutofillServiceLocked("setAugmentedAutofillWhitelistLocked",
|
||||
callingUid)) {
|
||||
return false;
|
||||
}
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "setAugmentedAutofillWhitelistLocked(packages=" + packages + ", activities="
|
||||
+ activities + ")");
|
||||
}
|
||||
whitelistForAugmentedAutofillPackages(packages);
|
||||
|
||||
// TODO(b/123100824): whitelist activities as well
|
||||
// TODO(b/122858578): log metrics
|
||||
return true;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean isCalledByAugmentedAutofillServiceLocked(@NonNull String methodName,
|
||||
int callingUid) {
|
||||
// Lazy load service first
|
||||
final RemoteAugmentedAutofillService service = getRemoteAugmentedAutofillServiceLocked();
|
||||
if (service == null) {
|
||||
Slog.w(TAG, methodName + "() called by UID " + callingUid
|
||||
+ ", but there is no augmented autofill service defined for user "
|
||||
+ getUserId());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getAugmentedAutofillServiceUidLocked() != callingUid) {
|
||||
Slog.w(TAG, methodName + "() called by UID " + callingUid
|
||||
+ ", but service UID is " + getAugmentedAutofillServiceUidLocked()
|
||||
+ " for user " + getUserId());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private int getAugmentedAutofillServiceUidLocked() {
|
||||
if (mRemoteAugmentedAutofillServiceInfo == null) {
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "getAugmentedAutofillServiceUid(): "
|
||||
+ "no mRemoteAugmentedAutofillServiceInfo");
|
||||
}
|
||||
return Process.INVALID_UID;
|
||||
}
|
||||
return mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
boolean isWhitelistedForAugmentedAutofillLocked(@NonNull ComponentName componentName) {
|
||||
// TODO(b/122595322): need to check whitelisted activities as well.
|
||||
final String packageName = componentName.getPackageName();
|
||||
return mWhitelistedAugmentAutofillPackages.contains(packageName);
|
||||
}
|
||||
|
||||
private void whitelistForAugmentedAutofillPackages(@NonNull List<String> packages) {
|
||||
// TODO(b/123100824): add CTS test for when it's null
|
||||
synchronized (mLock) {
|
||||
if (packages == null) {
|
||||
if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted augmented packages");
|
||||
mWhitelistedAugmentAutofillPackages.clear();
|
||||
} else {
|
||||
if (mMaster.verbose) Slog.v(TAG, "whitelisting augmented packages: " + packages);
|
||||
mWhitelistedAugmentAutofillPackages.addAll(packages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.service.autofill.augmented.AugmentedAutofillService;
|
||||
import android.service.autofill.augmented.IAugmentedAutofillService;
|
||||
import android.service.autofill.augmented.IFillCallback;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.view.autofill.AutofillId;
|
||||
import android.view.autofill.AutofillManager;
|
||||
@@ -57,7 +58,7 @@ final class RemoteAugmentedAutofillService
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ComponentName getComponentName(@NonNull String componentName,
|
||||
static Pair<ServiceInfo, ComponentName> getComponentName(@NonNull String componentName,
|
||||
@UserIdInt int userId, boolean isTemporary) {
|
||||
int flags = PackageManager.GET_META_DATA;
|
||||
if (!isTemporary) {
|
||||
@@ -78,7 +79,7 @@ final class RemoteAugmentedAutofillService
|
||||
Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
|
||||
return null;
|
||||
}
|
||||
return serviceComponent;
|
||||
return new Pair<>(serviceInfo, serviceComponent);
|
||||
}
|
||||
|
||||
@Override // from AbstractRemoteService
|
||||
|
||||
@@ -2613,13 +2613,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
+ " when server returned null for session " + this.id);
|
||||
}
|
||||
|
||||
final boolean isWhitelisted = mService
|
||||
.isWhitelistedForAugmentedAutofillLocked(mComponentName);
|
||||
|
||||
final String historyItem =
|
||||
"aug:id=" + id + " u=" + uid + " m=" + mode
|
||||
+ " a=" + ComponentName.flattenToShortString(mComponentName)
|
||||
+ " f=" + mCurrentViewId
|
||||
+ " s=" + remoteService.getComponentName();
|
||||
+ " s=" + remoteService.getComponentName()
|
||||
+ " w=" + isWhitelisted;
|
||||
mService.getMaster().logRequestLocked(historyItem);
|
||||
|
||||
if (!isWhitelisted) {
|
||||
if (sVerbose) {
|
||||
Slog.v(TAG, mComponentName.toShortString() + " is not whitelisted for "
|
||||
+ "augmented autofill");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue();
|
||||
|
||||
// TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
|
||||
|
||||
Reference in New Issue
Block a user