diff options
4 files changed, 100 insertions, 49 deletions
diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java index 435a671bcbbb..443bb745ad84 100644 --- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java +++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java @@ -295,6 +295,38 @@ public final class PresentationStatsEventLogger { }); } + /** + * Called for inline suggestions - inflated one at + * a time. If InlineSuggestions were filtered, + * reset the count be incrementing + */ + public void maybeIncrementCountShown() { + mEventInternal.ifPresent(event -> { + if (event.shouldResetShownCount) { + event.shouldResetShownCount = false; + event.mCountShown = 0; + } + + if (event.mCountShown == 0) { + // The first time suggestions are rendered + // set time stamp + maybeSetSuggestionPresentedTimestampMs(); + } + + event.mCountShown += 1; + }); + } + + /** + * Call this when UI is hidden. This will set a flag to reset count for inline. We do this + * instead of resetting right away in case there are 0 inline presentations after. + */ + public void markShownCountAsResettable() { + mEventInternal.ifPresent(event -> { + event.shouldResetShownCount = true; + }); + } + public void maybeSetCountShown(@Nullable List<Dataset> datasetList, AutofillId currentViewId) { mEventInternal.ifPresent(event -> { @@ -306,6 +338,13 @@ public final class PresentationStatsEventLogger { }); } + public void maybeSetCountShown(int datasets) { + mEventInternal.ifPresent( + event -> { + event.mCountShown = datasets; + }); + } + private static CountContainer getDatasetCountForAutofillId(@Nullable List<Dataset> datasetList, AutofillId currentViewId) { @@ -567,31 +606,36 @@ public final class PresentationStatsEventLogger { * <p>If the ViewState contains ViewState.STATE_AUTOFILLED, sets field_autofilled_timestamp_ms * else, set field_first_modified_timestamp_ms (if unset) and field_last_modified_timestamp_ms */ - public void onFieldTextUpdated(ViewState state) { - mEventInternal.ifPresent( - event -> { + public void onFieldTextUpdated(ViewState state, int length) { + mEventInternal.ifPresent(event -> { int timestamp = getElapsedTime(); // Focused id should be set before this is called - if (state.id != null && state.id.getViewId() != event.mFocusedId) { + if (state == null || state.id == null || state.id.getViewId() != event.mFocusedId) { // if these don't match, the currently field different than before Slog.w( TAG, - "current id: " - + state.id.getViewId() - + " is different than focused id: " - + event.mFocusedId); + "Bad view state for: " + event.mFocusedId); return; } + // Text changed because filling into form, just log Autofill timestamp if ((state.getState() & ViewState.STATE_AUTOFILLED) != 0) { event.mAutofilledTimestampMs = timestamp; - } else { - if (event.mFieldModifiedFirstTimestampMs == DEFAULT_VALUE_INT) { - event.mFieldModifiedFirstTimestampMs = timestamp; - } - event.mFieldModifiedLastTimestampMs = timestamp; + return; } - }); + + // Set length variables + if (event.mFieldFirstLength == DEFAULT_VALUE_INT) { + event.mFieldFirstLength = length; + } + event.mFieldLastLength = length; + + // Set timestamp variables + if (event.mFieldModifiedFirstTimestampMs == DEFAULT_VALUE_INT) { + event.mFieldModifiedFirstTimestampMs = timestamp; + } + event.mFieldModifiedLastTimestampMs = timestamp; + }); } public void setPresentationSelectedTimestamp() { @@ -652,15 +696,16 @@ public final class PresentationStatsEventLogger { /** Sets focused_autofill_id using view id */ public void maybeSetFocusedId(AutofillId id) { - maybeSetFocusedId(id.getViewId()); + mEventInternal.ifPresent( + event -> { + event.mFocusedId = id.getViewId(); + if (id.isVirtualInt()) { + event.mFocusedVirtualAutofillId = + id.getVirtualChildIntId() % 100; + } + }); } - /** Sets focused_autofill_id as long as mEventInternal is present */ - public void maybeSetFocusedId(int id) { - mEventInternal.ifPresent(event -> { - event.mFocusedId = id; - }); - } /** * Set views_filled_failure_count using failure count as long as mEventInternal * presents. @@ -812,7 +857,7 @@ public final class PresentationStatsEventLogger { @NotShownReason int mNoPresentationReason = NOT_SHOWN_REASON_UNKNOWN; boolean mIsDatasetAvailable; int mAvailableCount; - int mCountShown; + int mCountShown = 0; int mCountFilteredUserTyping; int mCountNotShownImePresentationNotDrawn; int mCountNotShownImeUserNotSeen; @@ -858,6 +903,9 @@ public final class PresentationStatsEventLogger { ArraySet<AutofillId> mAutofillIdsAttemptedAutofill; ArraySet<AutofillId> mAlreadyFilledAutofillIds = new ArraySet<>(); + + // Not logged - used for internal logic + boolean shouldResetShownCount = false; PresentationStatsEventInternal() {} } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index ecb0ad8b7d08..6c76aebc0288 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -30,7 +30,6 @@ import static android.service.autofill.Dataset.PICK_REASON_UNKNOWN; import static android.service.autofill.FillEventHistory.Event.UI_TYPE_CREDMAN_BOTTOM_SHEET; import static android.service.autofill.FillEventHistory.Event.UI_TYPE_DIALOG; import static android.service.autofill.FillEventHistory.Event.UI_TYPE_INLINE; -import static android.service.autofill.FillEventHistory.Event.UI_TYPE_MENU; import static android.service.autofill.FillEventHistory.Event.UI_TYPE_UNKNOWN; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE; @@ -2661,19 +2660,30 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // AutofillUiCallback @Override - public void onShown(int uiType) { + public void onShown(int uiType, int numDatasetsShown) { synchronized (mLock) { + mPresentationStatsEventLogger.maybeSetDisplayPresentationType(uiType); + if (uiType == UI_TYPE_INLINE) { - if (mLoggedInlineDatasetShown) { + // Inline Suggestions are inflated one at a time + // This number will be reset when filtered + // This will also call maybeSetSuggestionPresentedTimestampMs + mPresentationStatsEventLogger.maybeIncrementCountShown(); + + if (!mLoggedInlineDatasetShown) { // Chip inflation already logged, do not log again. // This is needed because every chip inflation will call this. - return; + mService.logDatasetShown(this.id, mClientState, uiType); + Slog.d(TAG, "onShown(): " + uiType + ", " + numDatasetsShown); } mLoggedInlineDatasetShown = true; + } else { + mPresentationStatsEventLogger.maybeSetCountShown(numDatasetsShown); + // Explicitly sets maybeSetSuggestionPresentedTimestampMs + mPresentationStatsEventLogger.maybeSetSuggestionPresentedTimestampMs(); + mService.logDatasetShown(this.id, mClientState, uiType); + Slog.d(TAG, "onShown(): " + uiType + ", " + numDatasetsShown); } - mService.logDatasetShown(this.id, mClientState, uiType); - mPresentationStatsEventLogger.maybeSetSuggestionPresentedTimestampMs(); - Slog.d(TAG, "onShown(): " + uiType); } } @@ -2739,6 +2749,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } mInlineSessionController.hideInlineSuggestionsUiLocked(id); + mPresentationStatsEventLogger.markShownCountAsResettable(); } } @@ -4868,7 +4879,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState currentView.maybeCallOnFillReady(flags); } } - mPresentationStatsEventLogger.onFieldTextUpdated(viewState); + if (textValue != null) { + mPresentationStatsEventLogger.onFieldTextUpdated(viewState, textValue.length()); + } if (viewState.id.equals(this.mCurrentViewId) && (viewState.getState() & ViewState.STATE_INLINE_SHOWN) != 0) { @@ -4965,8 +4978,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState synchronized (mLock) { final ViewState currentView = mViewStates.get(mCurrentViewId); currentView.setState(ViewState.STATE_FILL_DIALOG_SHOWN); - mPresentationStatsEventLogger.maybeSetCountShown( - response.getDatasets(), mCurrentViewId); mPresentationStatsEventLogger.maybeSetDisplayPresentationType(UI_TYPE_DIALOG); } // Just show fill dialog once, so disabled after shown. @@ -4987,10 +4998,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // back a response via callback. final ViewState currentView = mViewStates.get(mCurrentViewId); currentView.setState(ViewState.STATE_INLINE_SHOWN); - // TODO(b/234475358): Log more accurate value of number of inline suggestions - // shown, inflated, and filtered. - mPresentationStatsEventLogger.maybeSetCountShown( - response.getDatasets(), mCurrentViewId); mPresentationStatsEventLogger.maybeSetInlinePresentationAndSuggestionHostUid( mContext, userId); return; @@ -5004,12 +5011,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mService.getMaster().getMaxInputLengthForAutofill()); synchronized (mLock) { - mPresentationStatsEventLogger.maybeSetCountShown( - response.getDatasets(), mCurrentViewId); - mPresentationStatsEventLogger.maybeSetDisplayPresentationType(UI_TYPE_MENU); - } - - synchronized (mLock) { if (mUiShownTime == 0) { // Log first time UI is shown. mUiShownTime = SystemClock.elapsedRealtime(); @@ -5249,7 +5250,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void onInflate() { - Session.this.onShown(UI_TYPE_INLINE); + Session.this.onShown(UI_TYPE_INLINE, 1); } }, mService.getMaster().getMaxInputLengthForAutofill()); return mInlineSessionController.setInlineFillUiLocked(inlineFillUi); diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java index 8cc666b538ec..2e9a4dcb45aa 100644 --- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java @@ -102,7 +102,7 @@ public final class AutoFillUI { void cancelSession(); void requestShowSoftInput(AutofillId id); void requestFallbackFromFillDialog(); - void onShown(int uiType); + void onShown(int uiType, int datasetSize); } public AutoFillUI(@NonNull Context context) { @@ -246,9 +246,9 @@ public final class AutoFillUI { } @Override - public void onShown() { + public void onShown(int datasetSize) { if (mCallback != null) { - mCallback.onShown(UI_TYPE_MENU); + mCallback.onShown(UI_TYPE_MENU, datasetSize); } } @@ -462,7 +462,7 @@ public final class AutoFillUI { @Override public void onShown() { - callback.onShown(UI_TYPE_DIALOG); + mCallback.onShown(UI_TYPE_DIALOG, response.getDatasets().size()); } @Override diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java index 1831ecdaf77d..1bda70deac06 100644 --- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java @@ -16,6 +16,7 @@ package com.android.server.autofill.ui; import static android.service.autofill.FillResponse.FLAG_CREDENTIAL_MANAGER_RESPONSE; + import static com.android.server.autofill.Helper.paramsToString; import static com.android.server.autofill.Helper.sDebug; import static com.android.server.autofill.Helper.sFullScreenMode; @@ -90,7 +91,7 @@ final class FillUi { void onDatasetPicked(@NonNull Dataset dataset); void onCanceled(); void onDestroy(); - void onShown(); + void onShown(int datasetSize); void requestShowFillUi(int width, int height, IAutofillWindowPresenter windowPresenter); void requestHideFillUi(); @@ -742,7 +743,8 @@ final class FillUi { mWm.addView(mContentView, params); mOverlayControl.hideOverlays(); mShowing = true; - mCallback.onShown(); + int numShownDatasets = (mAdapter == null) ? 0 : mAdapter.getCount(); + mCallback.onShown(numShownDatasets); } else { mWm.updateViewLayout(mContentView, params); } |