From 5061db8a34371ffe3d43ae65918c023a2120a838 Mon Sep 17 00:00:00 2001 From: Adam He Date: Wed, 11 Mar 2020 15:58:27 -0700 Subject: [PATCH] Hide autofill highlight if filling only the focused field. Fixes: 150953184 Test: atest CtsAutoFillServiceTestCases Change-Id: Ifc23a70a41022931d6828ff9a14620bb8fc58604 --- api/test-current.txt | 2 +- .../augmented/AugmentedAutofillService.java | 3 +- core/java/android/view/View.java | 34 ++++++++++++++++--- .../view/autofill/AutofillManager.java | 28 ++++++++------- .../IAugmentedAutofillManagerClient.aidl | 3 +- .../view/autofill/IAutoFillManagerClient.aidl | 3 +- .../RemoteAugmentedAutofillService.java | 9 +++-- .../com/android/server/autofill/Session.java | 4 ++- 8 files changed, 62 insertions(+), 24 deletions(-) diff --git a/api/test-current.txt b/api/test-current.txt index 4f4c82b43e706..bd9117e417558 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4970,7 +4970,7 @@ package android.view { method public void resetRtlProperties(); method public boolean restoreFocusInCluster(int); method public boolean restoreFocusNotInCluster(); - method public void setAutofilled(boolean); + method public void setAutofilled(boolean, boolean); method public final void setFocusedInCluster(); method public void setIsRootNamespace(boolean); method public final void setShowingLayoutBounds(boolean); diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java index ed27dd5688232..5b08ae20f0711 100644 --- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java +++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java @@ -488,7 +488,8 @@ public abstract class AugmentedAutofillService extends Service { ids.add(pair.first); values.add(pair.second); } - mClient.autofill(mSessionId, ids, values); + final boolean hideHighlight = size == 1 && ids.get(0).equals(mFocusedId); + mClient.autofill(mSessionId, ids, values, hideHighlight); } public void setFillWindow(@NonNull FillWindow fillWindow) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6236e6ea31e90..04379621849a9 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3318,7 +3318,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Flag indicating that the view is autofilled * * @see #isAutofilled() - * @see #setAutofilled(boolean) + * @see #setAutofilled(boolean, boolean) */ private static final int PFLAG3_IS_AUTOFILLED = 0x10000; @@ -3428,6 +3428,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE * 11 PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK * 1 PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS + * 1 PFLAG4_AUTOFILL_HIDE_HIGHLIGHT * |-------|-------|-------|-------| */ @@ -3470,6 +3471,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100; + /** + * Flag indicating the field should not have yellow highlight when autofilled. + */ + private static final int PFLAG4_AUTOFILL_HIDE_HIGHLIGHT = 0x100; + /* End of masks for mPrivateFlags4 */ /** @hide */ @@ -9169,6 +9175,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0; } + /** + * @hide + */ + public boolean hideAutofillHighlight() { + return (mPrivateFlags4 & PFLAG4_AUTOFILL_HIDE_HIGHLIGHT) != 0; + } + /** * Gets the {@link View}'s current autofill value. * @@ -11741,7 +11754,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ @TestApi - public void setAutofilled(boolean isAutofilled) { + public void setAutofilled(boolean isAutofilled, boolean hideHighlight) { boolean wasChanged = isAutofilled != isAutofilled(); if (wasChanged) { @@ -11751,6 +11764,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED; } + if (hideHighlight) { + mPrivateFlags4 |= PFLAG4_AUTOFILL_HIDE_HIGHLIGHT; + } else { + mPrivateFlags4 &= ~PFLAG4_AUTOFILL_HIDE_HIGHLIGHT; + } + invalidate(); } } @@ -20569,6 +20588,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, state.mStartActivityRequestWhoSaved = mStartActivityRequestWho; state.mIsAutofilled = isAutofilled(); + state.mHideHighlight = hideAutofillHighlight(); state.mAutofillViewId = mAutofillViewId; return state; } @@ -20645,7 +20665,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved; } if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) { - setAutofilled(baseState.mIsAutofilled); + setAutofilled(baseState.mIsAutofilled, baseState.mHideHighlight); } if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) { // It can happen that views have the same view id and the restoration path will not @@ -24078,12 +24098,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled. + * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled, unless + * {@link #PFLAG4_AUTOFILL_HIDE_HIGHLIGHT} is enabled. * * @param canvas The canvas to draw on */ private void drawAutofilledHighlight(@NonNull Canvas canvas) { - if (isAutofilled()) { + if (isAutofilled() && !hideAutofillHighlight()) { Drawable autofilledHighlight = getAutofilledDrawable(); if (autofilledHighlight != null) { @@ -28526,6 +28547,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int mSavedData; String mStartActivityRequestWhoSaved; boolean mIsAutofilled; + boolean mHideHighlight; int mAutofillViewId; /** @@ -28549,6 +28571,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mSavedData = source.readInt(); mStartActivityRequestWhoSaved = source.readString(); mIsAutofilled = source.readBoolean(); + mHideHighlight = source.readBoolean(); mAutofillViewId = source.readInt(); } @@ -28568,6 +28591,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, out.writeInt(mSavedData); out.writeString(mStartActivityRequestWhoSaved); out.writeBoolean(mIsAutofilled); + out.writeBoolean(mHideHighlight); out.writeInt(mAutofillViewId); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index ce7cfa71e9a9a..a02e30e88666f 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1226,7 +1226,7 @@ public final class AutofillManager { // If the session is gone some fields might still be highlighted, hence we have to // remove the isAutofilled property even if no sessions are active. if (mLastAutofilledData == null) { - view.setAutofilled(false); + view.setAutofilled(false, false); } else { id = view.getAutofillId(); if (mLastAutofilledData.containsKey(id)) { @@ -1234,13 +1234,13 @@ public final class AutofillManager { valueWasRead = true; if (Objects.equals(mLastAutofilledData.get(id), value)) { - view.setAutofilled(true); + view.setAutofilled(true, false); } else { - view.setAutofilled(false); + view.setAutofilled(false, false); mLastAutofilledData.remove(id); } } else { - view.setAutofilled(false); + view.setAutofilled(false, false); } } @@ -2156,7 +2156,8 @@ public final class AutofillManager { * @param view The view that is to be autofilled * @param targetValue The value we want to fill into view */ - private void setAutofilledIfValuesIs(@NonNull View view, @Nullable AutofillValue targetValue) { + private void setAutofilledIfValuesIs(@NonNull View view, @Nullable AutofillValue targetValue, + boolean hideHighlight) { AutofillValue currentValue = view.getAutofillValue(); if (Objects.equals(currentValue, targetValue)) { synchronized (mLock) { @@ -2165,11 +2166,12 @@ public final class AutofillManager { } mLastAutofilledData.put(view.getAutofillId(), targetValue); } - view.setAutofilled(true); + view.setAutofilled(true, hideHighlight); } } - private void autofill(int sessionId, List ids, List values) { + private void autofill(int sessionId, List ids, List values, + boolean hideHighlight) { synchronized (mLock) { if (sessionId != mSessionId) { return; @@ -2228,7 +2230,7 @@ public final class AutofillManager { // synchronously. // If autofill happens async, the view is set to autofilled in // notifyValueChanged. - setAutofilledIfValuesIs(view, value); + setAutofilledIfValuesIs(view, value, hideHighlight); numApplied++; } @@ -3246,10 +3248,11 @@ public final class AutofillManager { } @Override - public void autofill(int sessionId, List ids, List values) { + public void autofill(int sessionId, List ids, List values, + boolean hideHighlight) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.post(() -> afm.autofill(sessionId, ids, values)); + afm.post(() -> afm.autofill(sessionId, ids, values, hideHighlight)); } } @@ -3387,10 +3390,11 @@ public final class AutofillManager { } @Override - public void autofill(int sessionId, List ids, List values) { + public void autofill(int sessionId, List ids, List values, + boolean hideHighlight) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.post(() -> afm.autofill(sessionId, ids, values)); + afm.post(() -> afm.autofill(sessionId, ids, values, hideHighlight)); } } diff --git a/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl b/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl index 03054dfdc7eab..8526c1e443c8a 100644 --- a/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl +++ b/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl @@ -38,7 +38,8 @@ interface IAugmentedAutofillManagerClient { /** * Autofills the activity with the contents of the values. */ - void autofill(int sessionId, in List ids, in List values); + void autofill(int sessionId, in List ids, in List values, + boolean hideHighlight); /** * Requests showing the fill UI. diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 3903665f2cded..4371b3c54f948 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -44,7 +44,8 @@ oneway interface IAutoFillManagerClient { /** * Autofills the activity with the contents of a dataset. */ - void autofill(int sessionId, in List ids, in List values); + void autofill(int sessionId, in List ids, in List values, + boolean hideHighlight); /** * Authenticates a fill response or a data set. diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java index e73f9ce4f7c09..53afa6e283d96 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java @@ -57,6 +57,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.os.IResultReceiver; import com.android.server.autofill.ui.InlineSuggestionFactory; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.TimeUnit; @@ -255,8 +256,12 @@ final class RemoteAugmentedAutofillService mCallbacks.logAugmentedAutofillSelected(sessionId, dataset.getId()); try { - client.autofill(sessionId, dataset.getFieldIds(), - dataset.getFieldValues()); + final ArrayList fieldIds = dataset.getFieldIds(); + final int size = fieldIds.size(); + final boolean hideHighlight = size == 1 + && fieldIds.get(0).equals(focusedId); + client.autofill(sessionId, fieldIds, dataset.getFieldValues(), + hideHighlight); } catch (RemoteException e) { Slog.w(TAG, "Encounter exception autofilling the values"); } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 538082d2f67eb..f022bc6bb6c56 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -3370,6 +3370,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final List ids = new ArrayList<>(entryCount); final List values = new ArrayList<>(entryCount); boolean waitingDatasetAuth = false; + boolean hideHighlight = (entryCount == 1 + && dataset.getFieldIds().get(0).equals(mCurrentViewId)); for (int i = 0; i < entryCount; i++) { if (dataset.getFieldValues().get(i) == null) { continue; @@ -3393,7 +3395,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); - mClient.autofill(id, ids, values); + mClient.autofill(id, ids, values, hideHighlight); if (dataset.getId() != null) { if (mSelectedDatasetIds == null) { mSelectedDatasetIds = new ArrayList<>();