diff --git a/api/test-current.txt b/api/test-current.txt index 52c05bbe6dabe..730a2a27df6ed 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 879f2840a1b3b..e665f065d952a 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. * @@ -11750,7 +11763,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) { @@ -11760,6 +11773,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(); } } @@ -20578,6 +20597,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, state.mStartActivityRequestWhoSaved = mStartActivityRequestWho; state.mIsAutofilled = isAutofilled(); + state.mHideHighlight = hideAutofillHighlight(); state.mAutofillViewId = mAutofillViewId; return state; } @@ -20654,7 +20674,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 @@ -24087,12 +24107,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) { @@ -28535,6 +28556,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int mSavedData; String mStartActivityRequestWhoSaved; boolean mIsAutofilled; + boolean mHideHighlight; int mAutofillViewId; /** @@ -28558,6 +28580,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mSavedData = source.readInt(); mStartActivityRequestWhoSaved = source.readString(); mIsAutofilled = source.readBoolean(); + mHideHighlight = source.readBoolean(); mAutofillViewId = source.readInt(); } @@ -28577,6 +28600,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 dda4e8b63a910..39a9ed4a82e7c 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1236,7 +1236,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)) { @@ -1244,13 +1244,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); } } @@ -2166,7 +2166,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) { @@ -2175,11 +2176,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; @@ -2238,7 +2240,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++; } @@ -3256,10 +3258,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)); } } @@ -3397,10 +3400,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 826500952e602..9693535e22864 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -3382,6 +3382,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; @@ -3405,7 +3407,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<>();