Loading services/autofill/bugfixes.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,16 @@ flag { } } flag { name: "multiple_fill_history" namespace: "autofill" description: "Allows tracking per Session FillEventHistory. As a bugfix flag to guard against DeviceConfig flag" bug: "365630157" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "add_session_id_to_client_state" namespace: "autofill" Loading services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +265 −92 Original line number Diff line number Diff line Loading @@ -152,6 +152,15 @@ final class AutofillManagerServiceImpl @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); /** * Cache of FillEventHistory for active Sessions. * * <p>New histories are added whenever a Session is created and are kept until Sessions are * removed through removeSessionLocked() */ @GuardedBy("mLock") private final SparseArray<FillEventHistory> mFillHistories = new SparseArray<>(); /** The last selection */ @GuardedBy("mLock") private FillEventHistory mEventHistory; Loading Loading @@ -663,6 +672,10 @@ final class AutofillManagerServiceImpl flags, mInputMethodManagerInternal, isPrimaryCredential); mSessions.put(newSession.id, newSession); if (Flags.multipleFillHistory() && !forAugmentedAutofillOnly) { mFillHistories.put(newSession.id, new FillEventHistory(sessionId, null)); } return newSession; } Loading Loading @@ -756,6 +769,28 @@ final class AutofillManagerServiceImpl TAG, "removeSessionLocked(): removed " + sessionId); } FillEventHistory history = null; if (Flags.multipleFillHistory() && mFillHistories != null) { history = mFillHistories.get(sessionId); mFillHistories.delete(sessionId); } if (mInfo == null || mInfo.getServiceInfo() == null) { if (sVerbose) { Slog.v(TAG, "removeSessionLocked(): early return because mInfo is null"); } return; } if (mMaster == null) { if (sVerbose) { Slog.v(TAG, "removeSessionLocked(): early return because mMaster is null"); } return; } RemoteFillService remoteService = new RemoteFillService( getContext(), Loading @@ -764,7 +799,8 @@ final class AutofillManagerServiceImpl /* callbacks= */ null, mMaster.isInstantServiceAllowed(), /* credentialAutofillService= */ null); remoteService.onSessionDestroyed(null); remoteService.onSessionDestroyed(history); } } Loading Loading @@ -886,6 +922,10 @@ final class AutofillManagerServiceImpl } } mSessions.clear(); if (Flags.multipleFillHistory()) { mFillHistories.clear(); } for (int i = 0; i < remoteFillServices.size(); i++) { remoteFillServices.valueAt(i).destroy(); } Loading Loading @@ -944,60 +984,132 @@ final class AutofillManagerServiceImpl return true; } @GuardedBy("mLock") void addEventToHistory(String eventName, int sessionId, Event event) { // For the singleton filleventhistory if (isValidEventLocked(eventName, sessionId)) { mEventHistory.addEvent(event); } if (Flags.multipleFillHistory()) { FillEventHistory history = mFillHistories.get(sessionId); if (history != null) { history.addEvent(event); } else { if (sVerbose) { Slog.v(TAG, eventName + " not logged because FillEventHistory is not tracked for: " + sessionId); } } } } /** * Updates the last fill selection when an authentication was selected. */ void setAuthenticationSelected(int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { int uiType, @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("setAuthenticationSelected()", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_AUTHENTICATION_SELECTED, null, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); } String methodName = "setAuthenticationSelected()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } /** * Updates the last fill selection when an dataset authentication was selected. */ void logDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { Event event = new Event( Event.TYPE_AUTHENTICATION_SELECTED, null, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } /** Updates the last fill selection when a dataset authentication was selected. */ void logDatasetAuthenticationSelected( @Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logDatasetAuthenticationSelected()", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); String methodName = "logDatasetAuthenticationSelected()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } /** * Updates the last fill selection when an save Ui is shown. */ void logSaveShown(int sessionId, @Nullable Bundle clientState) { void logSaveShown(int sessionId, @Nullable Bundle clientState, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logSaveShown()", sessionId)) { mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null, clientState, null, null, null, null, null, null, null, null, /* focusedId= */ null)); String methodName = "logSaveShown()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_SAVE_SHOWN, null, clientState, null, null, null, null, null, null, null, null, /* focusedId= */ null); addEventToHistory(methodName, sessionId, event); } } /** * Updates the last fill response when a dataset was selected. */ void logDatasetSelected(@Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { /** Updates the last fill response when a dataset was selected. */ void logDatasetSelected( @Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logDatasetSelected()", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_DATASET_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); String methodName = "logDatasetSelected()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_DATASET_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } Loading @@ -1005,40 +1117,75 @@ final class AutofillManagerServiceImpl * Updates the last fill response when a dataset is shown. */ void logDatasetShown(int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logDatasetShown", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null, String methodName = "logDatasetShown()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } void logViewEnteredForHistory( int sessionId, @Nullable Bundle clientState, FillEventHistory history, @Nullable AutofillId focusedId) { if (history.getEvents() != null) { // Do not log this event more than once for (Event event : history.getEvents()) { if (event.getType() == Event.TYPE_VIEW_REQUESTED_AUTOFILL) { if (sVerbose) { Slog.v(TAG, "logViewEntered: already logged TYPE_VIEW_REQUESTED_AUTOFILL"); } return; } } } history.addEvent( new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null, null, null, null, null, null, null, null, focusedId)); } /** * Updates the last fill response when a view was entered. */ void logViewEntered(int sessionId, @Nullable Bundle clientState, @Nullable AutofillId focusedId) { @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (!isValidEventLocked("logViewEntered", sessionId)) { String methodName = "logViewEntered()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } 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; // This log does not call addEventToHistory() because each distinct FillEventHistory // can only contain 1 TYPE_VIEW_REQUESTED_AUTOFILL event. Therefore, checking both // the singleton FillEventHistory and the per Session FillEventHistory is necessary if (isValidEventLocked(methodName, sessionId)) { logViewEnteredForHistory(sessionId, clientState, mEventHistory, focusedId); } if (Flags.multipleFillHistory()) { FillEventHistory history = mFillHistories.get(sessionId); if (history != null) { logViewEnteredForHistory(sessionId, clientState, history, focusedId); } } mEventHistory.addEvent( new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null, null, null, null, null, null, null, null, focusedId)); } } Loading Loading @@ -1096,12 +1243,12 @@ final class AutofillManagerServiceImpl @Nullable ArrayList<String> changedDatasetIds, @Nullable ArrayList<AutofillId> manuallyFilledFieldIds, @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds, @NonNull ComponentName appComponentName, boolean compatMode) { @NonNull ComponentName appComponentName, boolean compatMode, boolean shouldAdd) { logContextCommittedLocked(sessionId, clientState, selectedDatasets, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, /* detectedFieldIdsList= */ null, /* detectedFieldClassificationsList= */ null, appComponentName, compatMode, Event.NO_SAVE_UI_REASON_NONE); Event.NO_SAVE_UI_REASON_NONE, shouldAdd); } @GuardedBy("mLock") Loading @@ -1115,8 +1262,18 @@ final class AutofillManagerServiceImpl @Nullable ArrayList<AutofillId> detectedFieldIdsList, @Nullable ArrayList<FieldClassification> detectedFieldClassificationsList, @NonNull ComponentName appComponentName, boolean compatMode, @NoSaveReason int saveDialogNotShowReason) { if (isValidEventLocked("logDatasetNotSelected()", sessionId)) { @NoSaveReason int saveDialogNotShowReason, boolean shouldAdd) { String methodName = "logContextCommittedLocked()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } if (sVerbose) { Slog.v(TAG, "logContextCommitted() with FieldClassification: id=" + sessionId + ", selectedDatasets=" + selectedDatasets Loading @@ -1130,6 +1287,7 @@ final class AutofillManagerServiceImpl + ", compatMode=" + compatMode + ", saveDialogNotShowReason=" + saveDialogNotShowReason); } AutofillId[] detectedFieldsIds = null; FieldClassification[] detectedFieldClassifications = null; if (detectedFieldIdsList != null) { Loading @@ -1153,20 +1311,33 @@ final class AutofillManagerServiceImpl } final int averageScore = (int) ((totalScore * 100) / totalSize); mMetricsLogger.write(Helper .newLogMaker(MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES, appComponentName, getServicePackageName(), sessionId, compatMode) mMetricsLogger.write( Helper.newLogMaker( MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES, appComponentName, getServicePackageName(), sessionId, compatMode) .setCounterValue(numberFields) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE, averageScore)); } mEventHistory.addEvent(new Event(Event.TYPE_CONTEXT_COMMITTED, null, clientState, selectedDatasets, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldsIds, detectedFieldClassifications, saveDialogNotShowReason, /* focusedId= */ null)); } .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE, averageScore)); } Event event = new Event( Event.TYPE_CONTEXT_COMMITTED, null, clientState, selectedDatasets, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldsIds, detectedFieldClassifications, saveDialogNotShowReason, /* focusedId= */ null); addEventToHistory(methodName, sessionId, event); } /** Loading @@ -1175,6 +1346,8 @@ final class AutofillManagerServiceImpl * @param callingUid The calling uid * @return The history for the autofill or the augmented autofill events depending on the {@code * callingUid}, or {@code null} if there is none. * @deprecated Use {@link * android.service.autofill.AutofillService#onSessionDestroyed(FillEventHistory)} */ FillEventHistory getFillEventHistory(int callingUid) { synchronized (mLock) { Loading services/autofill/java/com/android/server/autofill/Session.java +58 −10 Original line number Diff line number Diff line Loading @@ -1962,7 +1962,7 @@ final class Session if (mLogViewEntered) { mLogViewEntered = false; mService.logViewEntered(id, null, mCurrentViewId); mService.logViewEntered(id, null, mCurrentViewId, shouldAddEventToHistory()); } } Loading Loading @@ -2866,7 +2866,12 @@ final class Session forceRemoveFromServiceLocked(); return; } mService.setAuthenticationSelected(id, mClientState, uiType, mCurrentViewId); mService.setAuthenticationSelected( id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); } Loading Loading @@ -2941,7 +2946,12 @@ final class Session if (!mLoggedInlineDatasetShown) { // Chip inflation already logged, do not log again. // This is needed because every chip inflation will call this. mService.logDatasetShown(this.id, mClientState, uiType, mCurrentViewId); mService.logDatasetShown( this.id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); Slog.d(TAG, "onShown(): " + uiType + ", " + numDatasetsShown); } mLoggedInlineDatasetShown = true; Loading @@ -2949,7 +2959,12 @@ final class Session mPresentationStatsEventLogger.logWhenDatasetShown(numDatasetsShown); // Explicitly sets maybeSetSuggestionPresentedTimestampMs mPresentationStatsEventLogger.maybeSetSuggestionPresentedTimestampMs(); mService.logDatasetShown(this.id, mClientState, uiType, mCurrentViewId); mService.logDatasetShown( this.id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); Slog.d(TAG, "onShown(): " + uiType + ", " + numDatasetsShown); } } Loading Loading @@ -3943,7 +3958,8 @@ final class Session detectedFieldClassifications, mComponentName, mCompatMode, saveDialogNotShowReason); saveDialogNotShowReason, shouldAddEventToHistory()); mSessionCommittedEventLogger.maybeSetCommitReason(commitReason); mSessionCommittedEventLogger.maybeSetRequestCount(mRequestCount); mSaveEventLogger.maybeSetSaveUiNotShownReason(saveDialogNotShowReason); Loading Loading @@ -4590,7 +4606,7 @@ final class Session } private void logSaveShown() { mService.logSaveShown(id, mClientState); mService.logSaveShown(id, mClientState, shouldAddEventToHistory()); } @Nullable Loading Loading @@ -5248,7 +5264,8 @@ final class Session // 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, mCurrentViewId); mService.logViewEntered( this.id, null, mCurrentViewId, shouldAddEventToHistory()); } // If this is the first time view is entered for inline, the last Loading Loading @@ -6863,8 +6880,13 @@ final class Session // Autofill it directly... if (dataset.getAuthentication() == null) { if (generateEvent) { mService.logDatasetSelected(dataset.getId(), id, mClientState, uiType, mCurrentViewId); mService.logDatasetSelected( dataset.getId(), id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); } if (mCurrentViewId != null) { mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId); Loading @@ -6875,7 +6897,7 @@ final class Session // ...or handle authentication. mService.logDatasetAuthenticationSelected(dataset.getId(), id, mClientState, uiType, mCurrentViewId); mCurrentViewId, shouldAddEventToHistory()); mPresentationStatsEventLogger.maybeSetAuthenticationType( AUTHENTICATION_TYPE_DATASET_AUTHENTICATION); // does not matter the value of isPrimary because null response won't be overridden. Loading Loading @@ -8018,6 +8040,32 @@ final class Session mService.getMaster().logRequestLocked(historyItem); } /** * Don't add secondary providers to FillEventHistory */ boolean shouldAddEventToHistory() { FillResponse lastResponse = null; synchronized (mLock) { lastResponse = getLastResponseLocked("shouldAddEventToHistory(%s)"); } // There might be events (like TYPE_VIEW_REQUESTED_AUTOFILL) that are // generated before FillRequest/FillResponse mechanism are started, so // still need to log it if (lastResponse == null) { return true; } if (mRequestId.isSecondaryProvider(lastResponse.getRequestId())) { // The request was to a secondary provider - don't log these events return false; } return true; } private void wtf(@Nullable Exception e, String fmt, Object... args) { final String message = String.format(fmt, args); synchronized (mLock) { Loading Loading
services/autofill/bugfixes.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,16 @@ flag { } } flag { name: "multiple_fill_history" namespace: "autofill" description: "Allows tracking per Session FillEventHistory. As a bugfix flag to guard against DeviceConfig flag" bug: "365630157" metadata { purpose: PURPOSE_BUGFIX } } flag { name: "add_session_id_to_client_state" namespace: "autofill" Loading
services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +265 −92 Original line number Diff line number Diff line Loading @@ -152,6 +152,15 @@ final class AutofillManagerServiceImpl @GuardedBy("mLock") private final SparseArray<Session> mSessions = new SparseArray<>(); /** * Cache of FillEventHistory for active Sessions. * * <p>New histories are added whenever a Session is created and are kept until Sessions are * removed through removeSessionLocked() */ @GuardedBy("mLock") private final SparseArray<FillEventHistory> mFillHistories = new SparseArray<>(); /** The last selection */ @GuardedBy("mLock") private FillEventHistory mEventHistory; Loading Loading @@ -663,6 +672,10 @@ final class AutofillManagerServiceImpl flags, mInputMethodManagerInternal, isPrimaryCredential); mSessions.put(newSession.id, newSession); if (Flags.multipleFillHistory() && !forAugmentedAutofillOnly) { mFillHistories.put(newSession.id, new FillEventHistory(sessionId, null)); } return newSession; } Loading Loading @@ -756,6 +769,28 @@ final class AutofillManagerServiceImpl TAG, "removeSessionLocked(): removed " + sessionId); } FillEventHistory history = null; if (Flags.multipleFillHistory() && mFillHistories != null) { history = mFillHistories.get(sessionId); mFillHistories.delete(sessionId); } if (mInfo == null || mInfo.getServiceInfo() == null) { if (sVerbose) { Slog.v(TAG, "removeSessionLocked(): early return because mInfo is null"); } return; } if (mMaster == null) { if (sVerbose) { Slog.v(TAG, "removeSessionLocked(): early return because mMaster is null"); } return; } RemoteFillService remoteService = new RemoteFillService( getContext(), Loading @@ -764,7 +799,8 @@ final class AutofillManagerServiceImpl /* callbacks= */ null, mMaster.isInstantServiceAllowed(), /* credentialAutofillService= */ null); remoteService.onSessionDestroyed(null); remoteService.onSessionDestroyed(history); } } Loading Loading @@ -886,6 +922,10 @@ final class AutofillManagerServiceImpl } } mSessions.clear(); if (Flags.multipleFillHistory()) { mFillHistories.clear(); } for (int i = 0; i < remoteFillServices.size(); i++) { remoteFillServices.valueAt(i).destroy(); } Loading Loading @@ -944,60 +984,132 @@ final class AutofillManagerServiceImpl return true; } @GuardedBy("mLock") void addEventToHistory(String eventName, int sessionId, Event event) { // For the singleton filleventhistory if (isValidEventLocked(eventName, sessionId)) { mEventHistory.addEvent(event); } if (Flags.multipleFillHistory()) { FillEventHistory history = mFillHistories.get(sessionId); if (history != null) { history.addEvent(event); } else { if (sVerbose) { Slog.v(TAG, eventName + " not logged because FillEventHistory is not tracked for: " + sessionId); } } } } /** * Updates the last fill selection when an authentication was selected. */ void setAuthenticationSelected(int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { int uiType, @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("setAuthenticationSelected()", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_AUTHENTICATION_SELECTED, null, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); } String methodName = "setAuthenticationSelected()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } /** * Updates the last fill selection when an dataset authentication was selected. */ void logDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { Event event = new Event( Event.TYPE_AUTHENTICATION_SELECTED, null, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } /** Updates the last fill selection when a dataset authentication was selected. */ void logDatasetAuthenticationSelected( @Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logDatasetAuthenticationSelected()", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); String methodName = "logDatasetAuthenticationSelected()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } /** * Updates the last fill selection when an save Ui is shown. */ void logSaveShown(int sessionId, @Nullable Bundle clientState) { void logSaveShown(int sessionId, @Nullable Bundle clientState, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logSaveShown()", sessionId)) { mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null, clientState, null, null, null, null, null, null, null, null, /* focusedId= */ null)); String methodName = "logSaveShown()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_SAVE_SHOWN, null, clientState, null, null, null, null, null, null, null, null, /* focusedId= */ null); addEventToHistory(methodName, sessionId, event); } } /** * Updates the last fill response when a dataset was selected. */ void logDatasetSelected(@Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { /** Updates the last fill response when a dataset was selected. */ void logDatasetSelected( @Nullable String selectedDataset, int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logDatasetSelected()", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_DATASET_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); String methodName = "logDatasetSelected()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_DATASET_SELECTED, selectedDataset, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } Loading @@ -1005,40 +1117,75 @@ final class AutofillManagerServiceImpl * Updates the last fill response when a dataset is shown. */ void logDatasetShown(int sessionId, @Nullable Bundle clientState, int uiType, @Nullable AutofillId focusedId) { @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (isValidEventLocked("logDatasetShown", sessionId)) { mEventHistory.addEvent( new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null, String methodName = "logDatasetShown()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } Event event = new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null, null, null, null, null, null, NO_SAVE_UI_REASON_NONE, uiType, focusedId)); uiType, focusedId); addEventToHistory(methodName, sessionId, event); } } void logViewEnteredForHistory( int sessionId, @Nullable Bundle clientState, FillEventHistory history, @Nullable AutofillId focusedId) { if (history.getEvents() != null) { // Do not log this event more than once for (Event event : history.getEvents()) { if (event.getType() == Event.TYPE_VIEW_REQUESTED_AUTOFILL) { if (sVerbose) { Slog.v(TAG, "logViewEntered: already logged TYPE_VIEW_REQUESTED_AUTOFILL"); } return; } } } history.addEvent( new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null, null, null, null, null, null, null, null, focusedId)); } /** * Updates the last fill response when a view was entered. */ void logViewEntered(int sessionId, @Nullable Bundle clientState, @Nullable AutofillId focusedId) { @Nullable AutofillId focusedId, boolean shouldAdd) { synchronized (mLock) { if (!isValidEventLocked("logViewEntered", sessionId)) { String methodName = "logViewEntered()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } 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; // This log does not call addEventToHistory() because each distinct FillEventHistory // can only contain 1 TYPE_VIEW_REQUESTED_AUTOFILL event. Therefore, checking both // the singleton FillEventHistory and the per Session FillEventHistory is necessary if (isValidEventLocked(methodName, sessionId)) { logViewEnteredForHistory(sessionId, clientState, mEventHistory, focusedId); } if (Flags.multipleFillHistory()) { FillEventHistory history = mFillHistories.get(sessionId); if (history != null) { logViewEnteredForHistory(sessionId, clientState, history, focusedId); } } mEventHistory.addEvent( new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null, null, null, null, null, null, null, null, focusedId)); } } Loading Loading @@ -1096,12 +1243,12 @@ final class AutofillManagerServiceImpl @Nullable ArrayList<String> changedDatasetIds, @Nullable ArrayList<AutofillId> manuallyFilledFieldIds, @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds, @NonNull ComponentName appComponentName, boolean compatMode) { @NonNull ComponentName appComponentName, boolean compatMode, boolean shouldAdd) { logContextCommittedLocked(sessionId, clientState, selectedDatasets, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, /* detectedFieldIdsList= */ null, /* detectedFieldClassificationsList= */ null, appComponentName, compatMode, Event.NO_SAVE_UI_REASON_NONE); Event.NO_SAVE_UI_REASON_NONE, shouldAdd); } @GuardedBy("mLock") Loading @@ -1115,8 +1262,18 @@ final class AutofillManagerServiceImpl @Nullable ArrayList<AutofillId> detectedFieldIdsList, @Nullable ArrayList<FieldClassification> detectedFieldClassificationsList, @NonNull ComponentName appComponentName, boolean compatMode, @NoSaveReason int saveDialogNotShowReason) { if (isValidEventLocked("logDatasetNotSelected()", sessionId)) { @NoSaveReason int saveDialogNotShowReason, boolean shouldAdd) { String methodName = "logContextCommittedLocked()"; if (!shouldAdd) { if (sVerbose) { Slog.v(TAG, methodName + " not logged because shouldAdd is false"); } return; } if (sVerbose) { Slog.v(TAG, "logContextCommitted() with FieldClassification: id=" + sessionId + ", selectedDatasets=" + selectedDatasets Loading @@ -1130,6 +1287,7 @@ final class AutofillManagerServiceImpl + ", compatMode=" + compatMode + ", saveDialogNotShowReason=" + saveDialogNotShowReason); } AutofillId[] detectedFieldsIds = null; FieldClassification[] detectedFieldClassifications = null; if (detectedFieldIdsList != null) { Loading @@ -1153,20 +1311,33 @@ final class AutofillManagerServiceImpl } final int averageScore = (int) ((totalScore * 100) / totalSize); mMetricsLogger.write(Helper .newLogMaker(MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES, appComponentName, getServicePackageName(), sessionId, compatMode) mMetricsLogger.write( Helper.newLogMaker( MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES, appComponentName, getServicePackageName(), sessionId, compatMode) .setCounterValue(numberFields) .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE, averageScore)); } mEventHistory.addEvent(new Event(Event.TYPE_CONTEXT_COMMITTED, null, clientState, selectedDatasets, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldsIds, detectedFieldClassifications, saveDialogNotShowReason, /* focusedId= */ null)); } .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE, averageScore)); } Event event = new Event( Event.TYPE_CONTEXT_COMMITTED, null, clientState, selectedDatasets, ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldsIds, detectedFieldClassifications, saveDialogNotShowReason, /* focusedId= */ null); addEventToHistory(methodName, sessionId, event); } /** Loading @@ -1175,6 +1346,8 @@ final class AutofillManagerServiceImpl * @param callingUid The calling uid * @return The history for the autofill or the augmented autofill events depending on the {@code * callingUid}, or {@code null} if there is none. * @deprecated Use {@link * android.service.autofill.AutofillService#onSessionDestroyed(FillEventHistory)} */ FillEventHistory getFillEventHistory(int callingUid) { synchronized (mLock) { Loading
services/autofill/java/com/android/server/autofill/Session.java +58 −10 Original line number Diff line number Diff line Loading @@ -1962,7 +1962,7 @@ final class Session if (mLogViewEntered) { mLogViewEntered = false; mService.logViewEntered(id, null, mCurrentViewId); mService.logViewEntered(id, null, mCurrentViewId, shouldAddEventToHistory()); } } Loading Loading @@ -2866,7 +2866,12 @@ final class Session forceRemoveFromServiceLocked(); return; } mService.setAuthenticationSelected(id, mClientState, uiType, mCurrentViewId); mService.setAuthenticationSelected( id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); } Loading Loading @@ -2941,7 +2946,12 @@ final class Session if (!mLoggedInlineDatasetShown) { // Chip inflation already logged, do not log again. // This is needed because every chip inflation will call this. mService.logDatasetShown(this.id, mClientState, uiType, mCurrentViewId); mService.logDatasetShown( this.id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); Slog.d(TAG, "onShown(): " + uiType + ", " + numDatasetsShown); } mLoggedInlineDatasetShown = true; Loading @@ -2949,7 +2959,12 @@ final class Session mPresentationStatsEventLogger.logWhenDatasetShown(numDatasetsShown); // Explicitly sets maybeSetSuggestionPresentedTimestampMs mPresentationStatsEventLogger.maybeSetSuggestionPresentedTimestampMs(); mService.logDatasetShown(this.id, mClientState, uiType, mCurrentViewId); mService.logDatasetShown( this.id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); Slog.d(TAG, "onShown(): " + uiType + ", " + numDatasetsShown); } } Loading Loading @@ -3943,7 +3958,8 @@ final class Session detectedFieldClassifications, mComponentName, mCompatMode, saveDialogNotShowReason); saveDialogNotShowReason, shouldAddEventToHistory()); mSessionCommittedEventLogger.maybeSetCommitReason(commitReason); mSessionCommittedEventLogger.maybeSetRequestCount(mRequestCount); mSaveEventLogger.maybeSetSaveUiNotShownReason(saveDialogNotShowReason); Loading Loading @@ -4590,7 +4606,7 @@ final class Session } private void logSaveShown() { mService.logSaveShown(id, mClientState); mService.logSaveShown(id, mClientState, shouldAddEventToHistory()); } @Nullable Loading Loading @@ -5248,7 +5264,8 @@ final class Session // 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, mCurrentViewId); mService.logViewEntered( this.id, null, mCurrentViewId, shouldAddEventToHistory()); } // If this is the first time view is entered for inline, the last Loading Loading @@ -6863,8 +6880,13 @@ final class Session // Autofill it directly... if (dataset.getAuthentication() == null) { if (generateEvent) { mService.logDatasetSelected(dataset.getId(), id, mClientState, uiType, mCurrentViewId); mService.logDatasetSelected( dataset.getId(), id, mClientState, uiType, mCurrentViewId, shouldAddEventToHistory()); } if (mCurrentViewId != null) { mInlineSessionController.hideInlineSuggestionsUiLocked(mCurrentViewId); Loading @@ -6875,7 +6897,7 @@ final class Session // ...or handle authentication. mService.logDatasetAuthenticationSelected(dataset.getId(), id, mClientState, uiType, mCurrentViewId); mCurrentViewId, shouldAddEventToHistory()); mPresentationStatsEventLogger.maybeSetAuthenticationType( AUTHENTICATION_TYPE_DATASET_AUTHENTICATION); // does not matter the value of isPrimary because null response won't be overridden. Loading Loading @@ -8018,6 +8040,32 @@ final class Session mService.getMaster().logRequestLocked(historyItem); } /** * Don't add secondary providers to FillEventHistory */ boolean shouldAddEventToHistory() { FillResponse lastResponse = null; synchronized (mLock) { lastResponse = getLastResponseLocked("shouldAddEventToHistory(%s)"); } // There might be events (like TYPE_VIEW_REQUESTED_AUTOFILL) that are // generated before FillRequest/FillResponse mechanism are started, so // still need to log it if (lastResponse == null) { return true; } if (mRequestId.isSecondaryProvider(lastResponse.getRequestId())) { // The request was to a secondary provider - don't log these events return false; } return true; } private void wtf(@Nullable Exception e, String fmt, Object... args) { final String message = String.format(fmt, args); synchronized (mLock) { Loading