Always start a manual request, even if view was already autofilled.

Fixes: 36034784
Test: CtsAutoFillServiceTestCases pass
Test: testAutofillManuallyAgainAfterAutomaticallyAutofilledBefore()
Test: testAutofillManuallyAgainAfterManuallyAutofilledBefore()

Change-Id: Ided8c42367b71766772bd364445510848db2adce
This commit is contained in:
Felipe Leme
2017-05-03 10:04:02 -07:00
parent 395f0ec8d2
commit 9a2e6058df
3 changed files with 72 additions and 23 deletions

View File

@@ -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) {

View File

@@ -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.
*
* <p>A new request will be started in 2 scenarios:
* <ol>
* <li>If the user manually requested autofill after the view was already filled.
* <li>If the view is part of a new partition.
* </ol>
*
* @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) {

View File

@@ -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;