Trigger Augmented Autofill when the standard service is not set.
Test: atest AugmentedLoginActivityTest#testAugmentedAutoFill_mainServiceDisabled Test: atest CtsAutoFillServiceTestCases # sanity check Fixes: 123100813 Change-Id: I16bf7f583a4be13584f1fa20c76c2b1c32cf4409
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
package android.view.autofill;
|
||||
|
||||
import static android.service.autofill.FillRequest.FLAG_AUGMENTED_AUTOFILL_REQUEST;
|
||||
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
|
||||
import static android.view.autofill.Helper.sDebug;
|
||||
import static android.view.autofill.Helper.sVerbose;
|
||||
@@ -228,6 +227,7 @@ public final class AutofillManager {
|
||||
/** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED = 0x1;
|
||||
/** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2;
|
||||
/** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4;
|
||||
/** @hide */ public static final int FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY = 0x8;
|
||||
|
||||
/** @hide */ public static final int FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1;
|
||||
|
||||
@@ -520,6 +520,13 @@ public final class AutofillManager {
|
||||
@GuardedBy("mLock")
|
||||
private boolean mForAugmentedAutofillOnly;
|
||||
|
||||
/**
|
||||
* When set, standard autofill is enabled, but sessions can still be created for augmented
|
||||
* autofill only.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private boolean mEnabledForAugmentedAutofillOnly;
|
||||
|
||||
/** @hide */
|
||||
public interface AutofillClient {
|
||||
/**
|
||||
@@ -946,7 +953,7 @@ public final class AutofillManager {
|
||||
|
||||
ensureServiceClientAddedIfNeededLocked();
|
||||
|
||||
if (!mEnabled) {
|
||||
if (!mEnabled && !mEnabledForAugmentedAutofillOnly) {
|
||||
if (sVerbose) Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled");
|
||||
|
||||
if (mCallback != null) {
|
||||
@@ -988,7 +995,7 @@ public final class AutofillManager {
|
||||
void notifyViewExitedLocked(@NonNull View view) {
|
||||
ensureServiceClientAddedIfNeededLocked();
|
||||
|
||||
if (mEnabled && isActiveLocked()) {
|
||||
if ((mEnabled || mEnabledForAugmentedAutofillOnly) && isActiveLocked()) {
|
||||
// dont notify exited when Activity is already in background
|
||||
if (!isClientDisablingEnterExitEvent()) {
|
||||
final AutofillId id = view.getAutofillId();
|
||||
@@ -1104,7 +1111,7 @@ public final class AutofillManager {
|
||||
|
||||
ensureServiceClientAddedIfNeededLocked();
|
||||
|
||||
if (!mEnabled) {
|
||||
if (!mEnabled && !mEnabledForAugmentedAutofillOnly) {
|
||||
if (sVerbose) {
|
||||
Log.v(TAG, "ignoring notifyViewEntered(" + id + "): disabled");
|
||||
}
|
||||
@@ -1155,7 +1162,7 @@ public final class AutofillManager {
|
||||
private void notifyViewExitedLocked(@NonNull View view, int virtualId) {
|
||||
ensureServiceClientAddedIfNeededLocked();
|
||||
|
||||
if (mEnabled && isActiveLocked()) {
|
||||
if ((mEnabled || mEnabledForAugmentedAutofillOnly) && isActiveLocked()) {
|
||||
// don't notify exited when Activity is already in background
|
||||
if (!isClientDisablingEnterExitEvent()) {
|
||||
final AutofillId id = getAutofillId(view, virtualId);
|
||||
@@ -1674,14 +1681,17 @@ public final class AutofillManager {
|
||||
private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds,
|
||||
@NonNull AutofillValue value, int flags) {
|
||||
if (mEnteredForAugmentedAutofillIds != null
|
||||
&& mEnteredForAugmentedAutofillIds.contains(id)) {
|
||||
&& mEnteredForAugmentedAutofillIds.contains(id)
|
||||
|| mEnabledForAugmentedAutofillOnly) {
|
||||
if (sVerbose) Log.v(TAG, "Starting session for augmented autofill on " + id);
|
||||
flags |= FLAG_AUGMENTED_AUTOFILL_REQUEST;
|
||||
flags |= FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
|
||||
}
|
||||
if (sVerbose) {
|
||||
Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value
|
||||
+ ", flags=" + flags + ", state=" + getStateAsStringLocked()
|
||||
+ ", compatMode=" + isCompatibilityModeEnabledLocked()
|
||||
+ ", augmentedOnly=" + mForAugmentedAutofillOnly
|
||||
+ ", enabledAugmentedOnly=" + mEnabledForAugmentedAutofillOnly
|
||||
+ ", enteredIds=" + mEnteredIds);
|
||||
}
|
||||
if (mState != STATE_UNKNOWN && !isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) {
|
||||
@@ -1776,7 +1786,8 @@ public final class AutofillManager {
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void ensureServiceClientAddedIfNeededLocked() {
|
||||
if (getClient() == null) {
|
||||
final AutofillClient client = getClient();
|
||||
if (client == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1785,11 +1796,18 @@ public final class AutofillManager {
|
||||
try {
|
||||
final int userId = mContext.getUserId();
|
||||
final SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
|
||||
mService.addClient(mServiceClient, userId, receiver);
|
||||
mService.addClient(mServiceClient, client.autofillClientGetComponentName(),
|
||||
userId, receiver);
|
||||
final int flags = receiver.getIntResult();
|
||||
mEnabled = (flags & FLAG_ADD_CLIENT_ENABLED) != 0;
|
||||
sDebug = (flags & FLAG_ADD_CLIENT_DEBUG) != 0;
|
||||
sVerbose = (flags & FLAG_ADD_CLIENT_VERBOSE) != 0;
|
||||
mEnabledForAugmentedAutofillOnly = (flags
|
||||
& FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY) != 0;
|
||||
if (sVerbose) {
|
||||
Log.v(TAG, "receiver results: flags=" + flags + " enabled=" + mEnabled
|
||||
+ ", enabledForAugmentedOnly: " + mEnabledForAugmentedAutofillOnly);
|
||||
}
|
||||
final IAutoFillManager service = mService;
|
||||
final IAutoFillManagerClient serviceClient = mServiceClient;
|
||||
mServiceClientCleaner = Cleaner.create(this, () -> {
|
||||
@@ -2406,6 +2424,7 @@ public final class AutofillManager {
|
||||
pw.print(" ("); pw.print(client.autofillClientGetActivityToken()); pw.println(')');
|
||||
}
|
||||
pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled);
|
||||
pw.print(pfx); pw.print("enabledAugmentedOnly: "); pw.println(mForAugmentedAutofillOnly);
|
||||
pw.print(pfx); pw.print("hasService: "); pw.println(mService != null);
|
||||
pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null);
|
||||
pw.print(pfx); pw.print("onInvisibleCalled "); pw.println(mOnInvisibleCalled);
|
||||
|
||||
@@ -37,7 +37,8 @@ import com.android.internal.os.IResultReceiver;
|
||||
*/
|
||||
oneway interface IAutoFillManager {
|
||||
// Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE
|
||||
void addClient(in IAutoFillManagerClient client, int userId, in IResultReceiver result);
|
||||
void addClient(in IAutoFillManagerClient client, in ComponentName componentName, int userId,
|
||||
in IResultReceiver result);
|
||||
void removeClient(in IAutoFillManagerClient client, int userId);
|
||||
void startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
|
||||
in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
|
||||
|
||||
@@ -942,12 +942,14 @@ public final class AutofillManagerService
|
||||
|
||||
final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
|
||||
@Override
|
||||
public void addClient(IAutoFillManagerClient client, int userId,
|
||||
@NonNull IResultReceiver receiver) {
|
||||
public void addClient(IAutoFillManagerClient client, ComponentName componentName,
|
||||
int userId, IResultReceiver receiver) {
|
||||
int flags = 0;
|
||||
synchronized (mLock) {
|
||||
if (getServiceForUserLocked(userId).addClientLocked(client)) {
|
||||
flags |= AutofillManager.FLAG_ADD_CLIENT_ENABLED;
|
||||
final int enabledFlags = getServiceForUserLocked(userId).addClientLocked(client,
|
||||
componentName);
|
||||
if (enabledFlags != 0) {
|
||||
flags |= enabledFlags;
|
||||
}
|
||||
if (sDebug) {
|
||||
flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG;
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.server.autofill;
|
||||
|
||||
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
|
||||
import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
|
||||
import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED;
|
||||
import static android.view.autofill.AutofillManager.FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
|
||||
import static android.view.autofill.AutofillManager.FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY;
|
||||
import static android.view.autofill.AutofillManager.NO_SESSION;
|
||||
|
||||
@@ -54,7 +56,6 @@ import android.service.autofill.FieldClassification;
|
||||
import android.service.autofill.FieldClassification.Match;
|
||||
import android.service.autofill.FillEventHistory;
|
||||
import android.service.autofill.FillEventHistory.Event;
|
||||
import android.service.autofill.FillRequest;
|
||||
import android.service.autofill.FillResponse;
|
||||
import android.service.autofill.IAutoFillService;
|
||||
import android.service.autofill.UserData;
|
||||
@@ -242,13 +243,28 @@ final class AutofillManagerServiceImpl
|
||||
return mAutofillCompatState.getUrlBarResourceIds(packageName, mUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the client and return the proper flags
|
||||
*
|
||||
* @return {@code 0} if disabled, {@code FLAG_ADD_CLIENT_ENABLED} if enabled (it might be
|
||||
* OR'ed with {@code FLAG_AUGMENTED_AUTOFILL_REQUEST}).
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
boolean addClientLocked(IAutoFillManagerClient client) {
|
||||
int addClientLocked(IAutoFillManagerClient client, ComponentName componentName) {
|
||||
if (mClients == null) {
|
||||
mClients = new RemoteCallbackList<>();
|
||||
}
|
||||
mClients.register(client);
|
||||
return isEnabledLocked();
|
||||
|
||||
if (isEnabledLocked()) return FLAG_ADD_CLIENT_ENABLED;
|
||||
|
||||
// Check if it's enabled for augmented autofill
|
||||
if (isSetupCompletedLocked() && isWhitelistedForAugmentedAutofillLocked(componentName)) {
|
||||
return FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY;
|
||||
}
|
||||
|
||||
// No flags / disabled
|
||||
return 0;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@@ -286,7 +302,7 @@ final class AutofillManagerServiceImpl
|
||||
*
|
||||
* @return {@code long} whose right-most 32 bits represent the session id (which is always
|
||||
* non-negative), and the left-most contains extra flags (currently either {@code 0} or
|
||||
* {@link FillRequest#FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}).
|
||||
* {@link AutofillManager#FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY}).
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
long startSessionLocked(@NonNull IBinder activityToken, int taskId, int uid,
|
||||
@@ -294,26 +310,27 @@ final class AutofillManagerServiceImpl
|
||||
@NonNull Rect virtualBounds, @Nullable AutofillValue value, boolean hasCallback,
|
||||
@NonNull ComponentName componentName, boolean compatMode,
|
||||
boolean bindInstantServiceAllowed, int flags) {
|
||||
if (!isEnabledLocked()) {
|
||||
// FLAG_AUGMENTED_AUTOFILL_REQUEST is set in the flags when standard autofill is disabled
|
||||
// but the package is whitelisted for augmented autofill
|
||||
boolean forAugmentedAutofillOnly = (flags
|
||||
& FLAG_ADD_CLIENT_ENABLED_FOR_AUGMENTED_AUTOFILL_ONLY) != 0;
|
||||
if (!isEnabledLocked() && !forAugmentedAutofillOnly) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final String shortComponentName = componentName.toShortString();
|
||||
boolean forAugmentedAutofillOnly = false;
|
||||
|
||||
if (isAutofillDisabledLocked(componentName)) {
|
||||
// Service disabled autofill; that means no session, unless the activity is whitelisted
|
||||
// for augmented autofill
|
||||
if (!forAugmentedAutofillOnly && isAutofillDisabledLocked(componentName)) {
|
||||
// Standard autofill is enabled, but service disabled autofill for this activity; that
|
||||
// means no session, unless the activity is whitelisted for augmented autofill
|
||||
if (isWhitelistedForAugmentedAutofillLocked(componentName)) {
|
||||
if (sDebug) {
|
||||
Slog.d(TAG, "startSession(" + shortComponentName + "): disabled by service but "
|
||||
Slog.d(TAG, "startSession(" + componentName + "): disabled by service but "
|
||||
+ "whitelisted for augmented autofill");
|
||||
}
|
||||
forAugmentedAutofillOnly = true;
|
||||
|
||||
} else {
|
||||
if (sDebug) {
|
||||
Slog.d(TAG, "startSession(" + shortComponentName + "): ignored because "
|
||||
Slog.d(TAG, "startSession(" + componentName + "): ignored because "
|
||||
+ "disabled by service and not whitelisted for augmented autofill");
|
||||
}
|
||||
final IAutoFillManagerClient client = IAutoFillManagerClient.Stub
|
||||
@@ -323,7 +340,7 @@ final class AutofillManagerServiceImpl
|
||||
/* autofillableIds= */ null);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG,
|
||||
"Could not notify " + shortComponentName + " that it's disabled: " + e);
|
||||
"Could not notify " + componentName + " that it's disabled: " + e);
|
||||
}
|
||||
|
||||
return NO_SESSION;
|
||||
@@ -345,9 +362,11 @@ final class AutofillManagerServiceImpl
|
||||
return NO_SESSION;
|
||||
}
|
||||
|
||||
// Service can be null when it's only for augmented autofill
|
||||
String servicePackageName = mInfo == null ? null : mInfo.getServiceInfo().packageName;
|
||||
final String historyItem =
|
||||
"id=" + newSession.id + " uid=" + uid + " a=" + shortComponentName
|
||||
+ " s=" + mInfo.getServiceInfo().packageName
|
||||
"id=" + newSession.id + " uid=" + uid + " a=" + componentName.toShortString()
|
||||
+ " s=" + servicePackageName
|
||||
+ " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds
|
||||
+ " hc=" + hasCallback + " f=" + flags + " aa=" + forAugmentedAutofillOnly;
|
||||
mMaster.logRequestLocked(historyItem);
|
||||
@@ -485,9 +504,12 @@ final class AutofillManagerServiceImpl
|
||||
|
||||
assertCallerLocked(componentName, compatMode);
|
||||
|
||||
// It's null when the session is just for augmented autofill
|
||||
final ComponentName serviceComponentName = mInfo == null ? null
|
||||
: mInfo.getServiceInfo().getComponentName();
|
||||
final Session newSession = new Session(this, mUi, getContext(), mHandler, mUserId, mLock,
|
||||
sessionId, taskId, uid, activityToken, appCallbackToken, hasCallback,
|
||||
mUiLatencyHistory, mWtfHistory, mInfo.getServiceInfo().getComponentName(),
|
||||
mUiLatencyHistory, mWtfHistory, serviceComponentName,
|
||||
componentName, compatMode, bindInstantServiceAllowed, forAugmentedAutofillOnly,
|
||||
flags);
|
||||
mSessions.put(newSession.id, newSession);
|
||||
|
||||
@@ -185,6 +185,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
@GuardedBy("mLock")
|
||||
private DeathRecipient mClientVulture;
|
||||
|
||||
/**
|
||||
* Reference to the remote service.
|
||||
*
|
||||
* <p>Only {@code null} when the session is for augmented autofill only.
|
||||
*/
|
||||
@Nullable
|
||||
private final RemoteFillService mRemoteFillService;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@@ -293,6 +299,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
private final IAssistDataReceiver mAssistReceiver = new IAssistDataReceiver.Stub() {
|
||||
@Override
|
||||
public void onHandleAssistData(Bundle resultData) throws RemoteException {
|
||||
if (mRemoteFillService == null) {
|
||||
wtf(null, "onHandleAssistData() called without a remote service. "
|
||||
+ "mForAugmentedAutofillOnly: %s", mForAugmentedAutofillOnly);
|
||||
return;
|
||||
}
|
||||
final AssistStructure structure = resultData.getParcelable(ASSIST_KEY_STRUCTURE);
|
||||
if (structure == null) {
|
||||
Slog.e(TAG, "No assist structure - app might have crashed providing it");
|
||||
@@ -527,6 +538,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private void cancelCurrentRequestLocked() {
|
||||
if (mRemoteFillService == null) {
|
||||
wtf(null, "cancelCurrentRequestLocked() called without a remote service. "
|
||||
+ "mForAugmentedAutofillOnly: %s", mForAugmentedAutofillOnly);
|
||||
return;
|
||||
}
|
||||
final int canceledRequest = mRemoteFillService.cancelCurrentRequest();
|
||||
|
||||
// Remove the FillContext as there will never be a response for the service
|
||||
@@ -608,7 +624,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
@NonNull Context context, @NonNull Handler handler, int userId, @NonNull Object lock,
|
||||
int sessionId, int taskId, int uid, @NonNull IBinder activityToken,
|
||||
@NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory,
|
||||
@NonNull LocalLog wtfHistory, @NonNull ComponentName serviceComponentName,
|
||||
@NonNull LocalLog wtfHistory, @Nullable ComponentName serviceComponentName,
|
||||
@NonNull ComponentName componentName, boolean compatMode,
|
||||
boolean bindInstantServiceAllowed, boolean forAugmentedAutofillOnly, int flags) {
|
||||
if (sessionId < 0) {
|
||||
@@ -623,8 +639,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
mLock = lock;
|
||||
mUi = ui;
|
||||
mHandler = handler;
|
||||
mRemoteFillService = new RemoteFillService(context, serviceComponentName, userId, this,
|
||||
bindInstantServiceAllowed);
|
||||
mRemoteFillService = serviceComponentName == null ? null
|
||||
: new RemoteFillService(context, serviceComponentName, userId, this,
|
||||
bindInstantServiceAllowed);
|
||||
mActivityToken = activityToken;
|
||||
mHasCallback = hasCallback;
|
||||
mUiLatencyHistory = uiLatencyHistory;
|
||||
@@ -2035,6 +2052,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
+ id + " destroyed");
|
||||
return;
|
||||
}
|
||||
if (mRemoteFillService == null) {
|
||||
wtf(null, "callSaveLocked() called without a remote service. "
|
||||
+ "mForAugmentedAutofillOnly: %s", mForAugmentedAutofillOnly);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sVerbose) Slog.v(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
|
||||
|
||||
@@ -3045,7 +3067,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
||||
pw.print(prefix); pw.print("mAugmentedAutofillableIds: ");
|
||||
pw.println(mAugmentedAutofillableIds);
|
||||
}
|
||||
mRemoteFillService.dump(prefix, pw);
|
||||
if (mRemoteFillService != null) {
|
||||
mRemoteFillService.dump(prefix, pw);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpRequestLog(@NonNull PrintWriter pw, @NonNull LogMaker log) {
|
||||
|
||||
Reference in New Issue
Block a user