diff options
| author | 2023-02-09 22:44:46 +0000 | |
|---|---|---|
| committer | 2023-03-01 22:54:21 +0000 | |
| commit | 84484c133e394b3aa25a2cfd82c260dba64fa4f1 (patch) | |
| tree | 0115e822854d2f77ee10a7ba70e0916c13fe77cd | |
| parent | dc7f62fd11aa4a14f0acf5b614a0af68260fc221 (diff) | |
Add a new Autofill FillEvent - for when the user taps a field.
Test: atest
android.autofillservice.cts.inline.InlineFillEventHistoryTest
atest android.autofillservice.cts.dropdown.FillEventHistoryTest
Bug: 266231634
Change-Id: I96d5aea6a0e8d834ffda5eb593f9969a7b1826e8
Merged-In: I96d5aea6a0e8d834ffda5eb593f9969a7b1826e8
4 files changed, 92 insertions, 3 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 52cb4923de18..1f6be6d1ff50 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -39861,6 +39861,7 @@ package android.service.autofill { field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1 field public static final int TYPE_DATASET_SELECTED = 0; // 0x0 field public static final int TYPE_SAVE_SHOWN = 3; // 0x3 + field public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6; // 0x6 field public static final int UI_TYPE_DIALOG = 3; // 0x3 field public static final int UI_TYPE_INLINE = 2; // 0x2 field public static final int UI_TYPE_MENU = 1; // 0x1 diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java index b0e847cd53f9..5d58120ef5bb 100644 --- a/core/java/android/service/autofill/FillEventHistory.java +++ b/core/java/android/service/autofill/FillEventHistory.java @@ -233,6 +233,22 @@ public final class FillEventHistory implements Parcelable { */ public static final int TYPE_DATASETS_SHOWN = 5; + /** + * The app/user requested for a field to be Autofilled. + * + * This event is fired when the view has been entered (by user or app) in order + * to differentiate from FillRequests that have been pretriggered for FillDialogs. + * + * For example, the user might navigate away from a screen without tapping any + * fields. In this case, a FillRequest/FillResponse has been generated, but was + * not used for Autofilling. The user did not intend to see an Autofill result, + * but a FillRequest was still generated. This is different from when the user + * did tap on a field after the pretriggered FillRequest, this event will appear + * in the FillEventHistory, signaling that the user did intend to Autofill + * something. + */ + public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6; + /** @hide */ @IntDef(prefix = { "TYPE_" }, value = { TYPE_DATASET_SELECTED, @@ -240,7 +256,8 @@ public final class FillEventHistory implements Parcelable { TYPE_AUTHENTICATION_SELECTED, TYPE_SAVE_SHOWN, TYPE_CONTEXT_COMMITTED, - TYPE_DATASETS_SHOWN + TYPE_DATASETS_SHOWN, + TYPE_VIEW_REQUESTED_AUTOFILL }) @Retention(RetentionPolicy.SOURCE) @interface EventIds{} @@ -659,8 +676,8 @@ public final class FillEventHistory implements Parcelable { @Nullable AutofillId[] detectedFieldIds, @Nullable FieldClassification[] detectedFieldClassifications, int saveDialogNotShowReason, int uiType) { - mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN, - "eventType"); + mEventType = Preconditions.checkArgumentInRange(eventType, 0, + TYPE_VIEW_REQUESTED_AUTOFILL, "eventType"); mDatasetId = datasetId; mClientState = clientState; mSelectedDatasetIds = selectedDatasetIds; @@ -723,6 +740,8 @@ public final class FillEventHistory implements Parcelable { return "TYPE_CONTEXT_COMMITTED"; case TYPE_DATASETS_SHOWN: return "TYPE_DATASETS_SHOWN"; + case TYPE_VIEW_REQUESTED_AUTOFILL: + return "TYPE_VIEW_REQUESTED_AUTOFILL"; default: return "TYPE_UNKNOWN"; } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 43b816bae651..61032dc7a59c 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -849,6 +849,32 @@ final class AutofillManagerServiceImpl } } + + /** + * Updates the last fill response when a view was entered. + */ + void logViewEntered(int sessionId, @Nullable Bundle clientState) { + synchronized (mLock) { + if (!isValidEventLocked("logViewEntered", sessionId)) { + return; + } + + if (mEventHistory.getEvents() != null) { + // Do not log this event more than once + for (Event event : mEventHistory.getEvents()) { + if (event.getType() == Event.TYPE_VIEW_REQUESTED_AUTOFILL) { + Slog.v(TAG, "logViewEntered: already logged TYPE_VIEW_REQUESTED_AUTOFILL"); + return; + } + } + } + + mEventHistory.addEvent( + new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null, + null, null, null, null, null, null, null)); + } + } + void logAugmentedAutofillAuthenticationSelected(int sessionId, @Nullable String selectedDataset, @Nullable Bundle clientState) { synchronized (mLock) { diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 598521f31ff5..4a12e3843972 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -442,6 +442,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private boolean mPreviouslyFillDialogPotentiallyStarted; /** + * Keeps track of if the user entered view, this is used to + * distinguish Fill Request that did not have user interaction + * with ones that did. + * + * This is set to true when entering view - after FillDialog FillRequest + * or on plain user tap. + */ + @NonNull + @GuardedBy("mLock") + private boolean mLogViewEntered; + + /** * Keeps the fill dialog trigger ids of the last response. This invalidates * the trigger ids of the previous response. */ @@ -1289,6 +1301,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags)); + mLogViewEntered = false; } /** @@ -1413,6 +1426,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mService.setLastResponse(id, response); + synchronized (mLock) { + if (mLogViewEntered) { + mLogViewEntered = false; + mService.logViewEntered(id, null); + } + } + + final long disableDuration = response.getDisableDuration(); final boolean autofillDisabled = disableDuration > 0; if (autofillDisabled) { @@ -3545,6 +3566,28 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } + synchronized (mLock) { + if (!mLogViewEntered) { + // If the current request is for FillDialog (preemptive) + // then this is the first time that the view is entered + // (mLogViewEntered == false) in this case, setLastResponse() + // has already been called, so just log here. + // If the current request is not and (mLogViewEntered == false) + // then the last session is being tracked (setLastResponse not called) + // so this calling logViewEntered will be a nop. + // Calling logViewEntered() twice will only log it once + // TODO(271181979): this is broken for multiple partitions + mService.logViewEntered(this.id, null); + } + + // If this is the first time view is entered for inline, the last + // session is still being tracked, so logViewEntered() needs + // to be delayed until setLastResponse is called. + // For fill dialog requests case logViewEntered is already called above + // so this will do nothing. Assumption: only one fill dialog per session + mLogViewEntered = true; + } + // Previously, fill request will only start whenever a view is entered. // With Fill Dialog, request starts prior to view getting entered. So, we can't end // the event at this moment, otherwise we will be wrongly attributing fill dialog |