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:
+ *
+ * - If the user manually requested autofill after the view was already filled.
+ *
- 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;