diff options
3 files changed, 79 insertions, 15 deletions
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index fe51633b50eb..545aef5224b7 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -599,6 +599,10 @@ public class AssistStructure implements Parcelable { boolean mSanitized; HtmlInfo mHtmlInfo; + // POJO used to override some autofill-related values when the node is parcelized. + // Not written to parcel. + AutofillOverlay mAutofillOverlay; + int mX; int mY; int mScrollX; @@ -756,6 +760,7 @@ public class AssistStructure implements Parcelable { boolean writeSensitive = true; int flags = mFlags & ~FLAGS_ALL_CONTROL; + if (mId != View.NO_ID) { flags |= FLAGS_HAS_ID; } @@ -810,6 +815,13 @@ public class AssistStructure implements Parcelable { // Remove 'checked' from sanitized autofill request. writtenFlags = flags & ~FLAGS_CHECKED; } + if (mAutofillOverlay != null) { + if (mAutofillOverlay.focused) { + writtenFlags |= ViewNode.FLAGS_FOCUSED; + } else { + writtenFlags &= ~ViewNode.FLAGS_FOCUSED; + } + } out.writeInt(writtenFlags); if ((flags&FLAGS_HAS_ID) != 0) { @@ -829,7 +841,14 @@ public class AssistStructure implements Parcelable { out.writeParcelable(mAutofillId, 0); out.writeInt(mAutofillType); out.writeStringArray(mAutofillHints); - final AutofillValue sanitizedValue = writeSensitive ? mAutofillValue : null; + final AutofillValue sanitizedValue; + if (mAutofillOverlay != null && mAutofillOverlay.value != null) { + sanitizedValue = mAutofillOverlay.value; + } else if (writeSensitive) { + sanitizedValue = mAutofillValue; + } else { + sanitizedValue = null; + } out.writeParcelable(sanitizedValue, 0); out.writeStringArray(mAutofillOptions); if (mHtmlInfo instanceof Parcelable) { @@ -959,6 +978,11 @@ public class AssistStructure implements Parcelable { return mAutofillValue; } + /** @hide **/ + public void setAutofillOverlay(AutofillOverlay overlay) { + mAutofillOverlay = overlay; + } + /** * Gets the options that can be used to autofill this structure. * @@ -1340,6 +1364,16 @@ public class AssistStructure implements Parcelable { } } + /** + * POJO used to override some autofill-related values when the node is parcelized. + * + * @hide + */ + static public class AutofillOverlay { + public boolean focused; + public AutofillValue value; + } + static class ViewNodeBuilder extends ViewStructure { final AssistStructure mAssist; final ViewNode mNode; diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 801769cc42e1..1ffc82fb438f 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -29,6 +29,7 @@ import static com.android.server.autofill.Helper.VERBOSE; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.assist.AssistStructure; +import android.app.assist.AssistStructure.AutofillOverlay; import android.app.assist.AssistStructure.ViewNode; import android.app.assist.AssistStructure.WindowNode; import android.content.ComponentName; @@ -100,7 +101,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @NonNull private final String mPackageName; @GuardedBy("mLock") - private final Map<AutofillId, ViewState> mViewStates = new ArrayMap<>(); + private final ArrayMap<AutofillId, ViewState> mViewStates = new ArrayMap<>(); /** * Id of the View currently being displayed. @@ -517,10 +518,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (DEBUG) { Slog.d(TAG, "Creating viewState for " + id + " on " + getFlagAsString(flags)); } - viewState = new ViewState(this, id, this, ViewState.STATE_INITIAL); + viewState = new ViewState(this, id, value, this, ViewState.STATE_INITIAL); mViewStates.put(id, viewState); } else if ((flags & FLAG_VIEW_ENTERED) != 0) { - viewState = startPartitionLocked(id); + viewState = startPartitionLocked(id, value); } else { if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id); return; @@ -584,25 +585,45 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Slog.w(TAG, "updateLocked(): unknown flags " + flags + ": " + getFlagAsString(flags)); } - private ViewState startPartitionLocked(AutofillId id) { + private ViewState startPartitionLocked(AutofillId id, AutofillValue value) { if (DEBUG) { Slog.d(TAG, "Starting partition for view id " + id); } - final ViewState viewState = - new ViewState(this, id, this,ViewState.STATE_STARTED_PARTITION); - mViewStates.put(id, viewState); + final ViewState newViewState = + new ViewState(this, id, value, this,ViewState.STATE_STARTED_PARTITION); + mViewStates.put(id, newViewState); /* * TODO(b/33197203 , b/35707731): when start a new partition, it should * - * - add autofilled fields as sanitized - * - set focus on ViewStructure that triggered it * - pass the first onFillRequest() bundle * - optional: perhaps add a new flag onFilLRequest() to indicate it's a new partition? */ + + // Must update value of nodes so: + // - proper node is focused + // - autofillValue is sent back to service when it was previously autofilled + for (int i = 0; i < mViewStates.size(); i++) { + final ViewState viewState = mViewStates.valueAt(i); + + final ViewNode node = findViewNodeByIdLocked(viewState.id); + if (node == null) { + Slog.w(TAG, "startPartitionLocked(): no node for " + viewState.id); + continue; + } + + final AutofillValue initialValue = viewState.getInitialValue(); + final AutofillValue filledValue = viewState.getAutofilledValue(); + final AutofillOverlay overlay = new AutofillOverlay(); + if (filledValue != null && !filledValue.equals(initialValue)) { + overlay.value = filledValue; + } + overlay.focused = id.equals(viewState.id); + node.setAutofillOverlay(overlay); + } mRemoteFillService.onFillRequest(mStructure, null, 0); - return viewState; + return newViewState; } @Override @@ -695,7 +716,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (viewState != null) { viewState.setState(state); } else { - viewState = new ViewState(this, id, this, state); + viewState = new ViewState(this, id, null, this, state); if (DEBUG) { // TODO(b/33197203): change to VERBOSE once stable Slog.d(TAG, "Adding autofillable view with id " + id + " and state " + state); } diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java index 549f231367c6..f8919eeb060b 100644 --- a/services/autofill/java/com/android/server/autofill/ViewState.java +++ b/services/autofill/java/com/android/server/autofill/ViewState.java @@ -67,15 +67,17 @@ final class ViewState { private final Session mSession; private FillResponse mResponse; + private AutofillValue mInitialValue; private AutofillValue mCurrentValue; private AutofillValue mAutofilledValue; private Rect mVirtualBounds; private int mState; - ViewState(Session session, AutofillId id, Listener listener, int state) { + ViewState(Session session, AutofillId id, AutofillValue value, Listener listener, int state) { mSession = session; this.id = id; + mInitialValue = value; mListener = listener; mState = state; } @@ -110,6 +112,11 @@ final class ViewState { } @Nullable + AutofillValue getInitialValue() { + return mInitialValue; + } + + @Nullable FillResponse getResponse() { return mResponse; } @@ -184,14 +191,16 @@ final class ViewState { @Override public String toString() { - return "ViewState: [id=" + id + ", currentValue=" + mCurrentValue - + ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() +"]"; + return "ViewState: [id=" + id + ", initialValue=" + mInitialValue + + ", currentValue=" + mCurrentValue + ", autofilledValue=" + mAutofilledValue + + ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() + "]"; } void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("id:" ); pw.println(this.id); pw.print(prefix); pw.print("state:" ); pw.println(getStateAsString()); pw.print(prefix); pw.print("has response:" ); pw.println(mResponse != null); + pw.print(prefix); pw.print("initialValue:" ); pw.println(mInitialValue); pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue); pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue); pw.print(prefix); pw.print("virtualBounds:" ); pw.println(mVirtualBounds); |