diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java index 68ade63ac516c..cbf97ddc8abb4 100644 --- a/services/autofill/java/com/android/server/autofill/Helper.java +++ b/services/autofill/java/com/android/server/autofill/Helper.java @@ -20,7 +20,9 @@ import android.annotation.NonNull; import android.app.assist.AssistStructure; import android.app.assist.AssistStructure.ViewNode; import android.os.Bundle; +import android.util.DebugUtils; import android.view.autofill.AutofillId; +import android.view.autofill.AutofillManager; import java.util.Arrays; import java.util.Objects; @@ -40,6 +42,10 @@ public final class Helper { */ public static boolean sVerbose = false; + private Helper() { + throw new UnsupportedOperationException("contains static members only"); + } + static void append(StringBuilder builder, Bundle bundle) { if (bundle == null || !sVerbose) { builder.append("null"); @@ -62,8 +68,8 @@ public final class Helper { return builder.toString(); } - private Helper() { - throw new UnsupportedOperationException("contains static members only"); + static String getUpdateActionAsString(int action) { + return DebugUtils.flagsToString(AutofillManager.class, "ACTION_", action); } static ViewNode findViewNodeById(@NonNull AssistStructure structure, @NonNull AutofillId id) { diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 9d03fded6511a..23b734adaa9af 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -25,9 +25,13 @@ import static android.view.autofill.AutofillManager.ACTION_VALUE_CHANGED; import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED; import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED; +import static com.android.server.autofill.Helper.findViewNodeById; +import static com.android.server.autofill.Helper.getUpdateActionAsString; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sVerbose; -import static com.android.server.autofill.Helper.findViewNodeById; +import static com.android.server.autofill.ViewState.STATE_AUTOFILLED; +import static com.android.server.autofill.ViewState.STATE_FILLABLE; +import static com.android.server.autofill.ViewState.STATE_RESTARTED_SESSION; import android.annotation.NonNull; import android.annotation.Nullable; @@ -251,16 +255,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState continue; } - final AutofillValue initialValue = viewState.getInitialValue(); + final AutofillValue currentValue = viewState.getCurrentValue(); final AutofillValue filledValue = viewState.getAutofilledValue(); final AutofillOverlay overlay = new AutofillOverlay(); - if (filledValue != null && !filledValue.equals(initialValue)) { - overlay.value = filledValue; + + // Sanitizes the value if the current value matches what the service sent. + if (filledValue != null && filledValue.equals(currentValue)) { + overlay.value = currentValue; } + if (mCurrentViewId != null) { + // Updates the focus value. overlay.focused = mCurrentViewId.equals(viewState.id); + // Sanitizes the value of the focused field in a manual request. if (overlay.focused && (flags & FLAG_MANUAL_REQUEST) != 0) { - overlay.value = node.getAutofillValue(); + overlay.value = currentValue; } } node.setAutofillOverlay(overlay); @@ -886,6 +895,40 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mRemoteFillService.onSaveRequest(saveRequest); } + /** + * Starts (if necessary) a new fill request upon entering a view. + * + *

A new request will be started in 2 scenarios: + *

    + *
  1. If the user manually requested autofill after the view was already filled. + *
  2. If the view is part of a new partition. + *
+ * + * @param id The id of the view that is entered. + * @param viewState The view that is entered. + * @param flags The flag that was passed by the AutofillManager. + */ + private void requestNewFillResponseIfNecessaryLocked(@NonNull AutofillId id, + @NonNull ViewState viewState, int flags) { + // First check if this is a manual request after view was autofilled. + final int state = viewState.getState(); + final boolean restart = (state & STATE_AUTOFILLED) != 0 + && (flags & FLAG_MANUAL_REQUEST) != 0; + if (restart) { + if (sDebug) Slog.d(TAG, "Re-starting session on view " + id); + viewState.setState(STATE_RESTARTED_SESSION); + requestNewFillResponseLocked(flags); + return; + } + + // If it's not, then check if it it should start a partition. + if (shouldStartNewPartitionLocked(id)) { + if (sDebug) Slog.d(TAG, "Starting partition for view id " + id); + viewState.setState(ViewState.STATE_STARTED_PARTITION); + requestNewFillResponseLocked(flags); + } + } + /** * Determines if a new partition should be started for an id. * @@ -942,6 +985,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + id + " destroyed"); return; } + if (sVerbose) { + Slog.v(TAG, "updateLocked(): id=" + id + ", action=" + getUpdateActionAsString(action) + + ", flags=" + flags); + } ViewState viewState = mViewStates.get(id); if (viewState == null) { @@ -996,13 +1043,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } break; case ACTION_VIEW_ENTERED: - if (shouldStartNewPartitionLocked(id)) { - if (sDebug) { - Slog.d(TAG, "Starting partition for view id " + viewState.id); - } - viewState.setState(ViewState.STATE_STARTED_PARTITION); - requestNewFillResponseLocked(flags); - } + requestNewFillResponseIfNecessaryLocked(id, viewState, flags); // Remove the UI if the ViewState has changed. if (mCurrentViewId != viewState.id) { diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java index d114e14523732..561c603ea3b00 100644 --- a/services/autofill/java/com/android/server/autofill/ViewState.java +++ b/services/autofill/java/com/android/server/autofill/ViewState.java @@ -47,23 +47,25 @@ final class ViewState { private static final String TAG = "ViewState"; // NOTE: state constants must be public because of flagstoString(). - public static final int STATE_UNKNOWN = 0x00; + public static final int STATE_UNKNOWN = 0x000; /** Initial state. */ - public static final int STATE_INITIAL = 0x01; + public static final int STATE_INITIAL = 0x001; /** View id is present in a dataset returned by the service. */ - public static final int STATE_FILLABLE = 0x02; + public static final int STATE_FILLABLE = 0x002; /** View was autofilled after user selected a dataset. */ - public static final int STATE_AUTOFILLED = 0x04; + public static final int STATE_AUTOFILLED = 0x004; /** View value was changed, but not by the service. */ - public static final int STATE_CHANGED = 0x08; + public static final int STATE_CHANGED = 0x008; /** Set only in the View that started a session. */ - public static final int STATE_STARTED_SESSION = 0x10; + public static final int STATE_STARTED_SESSION = 0x010; /** View that started a new partition when focused on. */ - public static final int STATE_STARTED_PARTITION = 0x20; + public static final int STATE_STARTED_PARTITION = 0x020; /** User select a dataset in this view, but service must authenticate first. */ - public static final int STATE_WAITING_DATASET_AUTH = 0x40; + public static final int STATE_WAITING_DATASET_AUTH = 0x040; /** Service does not care about this view. */ - public static final int STATE_IGNORED = 0x80; + public static final int STATE_IGNORED = 0x080; + /** User manually request autofill in this view, after it was already autofilled. */ + public static final int STATE_RESTARTED_SESSION = 0x100; public final AutofillId id;