Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7192f069 authored by Jiewen Lei's avatar Jiewen Lei Committed by Android (Google) Code Review
Browse files

Merge "Add the logging of save event for Autofill framework." into udc-dev

parents 8138fa29 c31a0125
Loading
Loading
Loading
Loading
+9 −11
Original line number Diff line number Diff line
@@ -17,16 +17,16 @@
package com.android.server.autofill;

import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__MENU;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__DIALOG;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__INLINE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__MENU;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_FAILURE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_RESULT_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_SUCCESS;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__AUTHENTICATION_TYPE_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__DATASET_AUTHENTICATION;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_TYPE__FULL_AUTHENTICATION;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_RESULT_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_SUCCESS;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__AUTHENTICATION_RESULT__AUTHENTICATION_FAILURE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_CANCELLED;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_FAILURE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_FILL_RESPONSE_REPORTED__RESPONSE_STATUS__RESPONSE_STATUS_SESSION_DESTROYED;
@@ -37,12 +37,7 @@ import static com.android.server.autofill.Helper.sVerbose;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.service.autofill.Dataset;
import android.text.TextUtils;
import android.util.Slog;
import android.view.autofill.AutofillId;

@@ -154,6 +149,9 @@ public final class FillResponseEventLogger {
  // succeeded.
  public static final int AVAILABLE_COUNT_WHEN_FILL_REQUEST_FAILED_OR_TIMEOUT = -1;

  // Log a magic number to indicate that the FillResponse contains a saveTriggerId.
  public static final int HAVE_SAVE_TRIGGER_ID = 1;

  private final int mSessionId;
  private Optional<FillResponseEventInternal> mEventInternal;

+9 −6
Original line number Diff line number Diff line
@@ -23,8 +23,10 @@ import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_RE
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NONE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NO_SAVE_INFO;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_NO_VALUE_CHANGED;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_SESSION_DESTROYED;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_OPTIONAL_ID_CHANGE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE;
import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_SHOWN_REASON__SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET;
@@ -32,11 +34,6 @@ import static com.android.internal.util.FrameworkStatsLog.AUTOFILL_SAVE_EVENT_RE
import static com.android.server.autofill.Helper.sVerbose;

import android.annotation.IntDef;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;

import com.android.internal.util.FrameworkStatsLog;
@@ -74,10 +71,12 @@ public final class SaveEventLogger {
      NO_SAVE_REASON_NONE,
      NO_SAVE_REASON_NO_SAVE_INFO,
      NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG,
      NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG,
      NO_SAVE_REASON_HAS_EMPTY_REQUIRED,
      NO_SAVE_REASON_NO_VALUE_CHANGED,
      NO_SAVE_REASON_FIELD_VALIDATION_FAILED,
      NO_SAVE_REASON_DATASET_MATCH
      NO_SAVE_REASON_DATASET_MATCH,
      NO_SAVE_REASON_SESSION_DESTROYED
  })
  @Retention(RetentionPolicy.SOURCE)
  public @interface SaveUiNotShownReason {
@@ -108,6 +107,10 @@ public final class SaveEventLogger {
      AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_FIELD_VALIDATION_FAILED;
  public static final int NO_SAVE_REASON_DATASET_MATCH =
      AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_DATASET_MATCH;
  public static final int NO_SAVE_REASON_SESSION_DESTROYED =
      AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_SESSION_DESTROYED;
  public static final int NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG =
      AUTOFILL_SAVE_EVENT_REPORTED__SAVE_UI_NOT_SHOWN_REASON__NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG;

  private final int mSessionId;
  private Optional<SaveEventInternal> mEventInternal;
+107 −2
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import static com.android.server.autofill.FillRequestEventLogger.TRIGGER_REASON_
import static com.android.server.autofill.FillRequestEventLogger.TRIGGER_REASON_PRE_TRIGGER;
import static com.android.server.autofill.FillRequestEventLogger.TRIGGER_REASON_SERVED_FROM_CACHED_RESPONSE;
import static com.android.server.autofill.FillResponseEventLogger.AVAILABLE_COUNT_WHEN_FILL_REQUEST_FAILED_OR_TIMEOUT;
import static com.android.server.autofill.FillResponseEventLogger.HAVE_SAVE_TRIGGER_ID;
import static com.android.server.autofill.FillResponseEventLogger.RESPONSE_STATUS_FAILURE;
import static com.android.server.autofill.FillResponseEventLogger.RESPONSE_STATUS_SESSION_DESTROYED;
import static com.android.server.autofill.FillResponseEventLogger.RESPONSE_STATUS_SUCCESS;
@@ -58,8 +59,22 @@ import static com.android.server.autofill.Helper.toArray;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_NO_FOCUS;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_REQUEST_FAILED;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_REQUEST_TIMEOUT;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_SESSION_COMMITTED_PREMATURELY;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_VIEW_CHANGED;
import static com.android.server.autofill.PresentationStatsEventLogger.NOT_SHOWN_REASON_VIEW_FOCUS_CHANGED;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_DATASET_MATCH;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_FIELD_VALIDATION_FAILED;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_HAS_EMPTY_REQUIRED;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_NONE;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_NO_SAVE_INFO;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_NO_VALUE_CHANGED;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_SESSION_DESTROYED;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG;
import static com.android.server.autofill.SaveEventLogger.NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG;
import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_OPTIONAL_ID_CHANGE;
import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE;
import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET;
import static com.android.server.autofill.SaveEventLogger.SAVE_UI_SHOWN_REASON_UNKNOWN;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;

@@ -457,6 +472,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
    @GuardedBy("mLock")
    private FillResponseEventLogger mFillResponseEventLogger;

    @NonNull
    @GuardedBy("mLock")
    private SaveEventLogger mSaveEventLogger;

    @NonNull
    @GuardedBy("mLock")
    private SessionCommittedEventLogger mSessionCommittedEventLogger;

    /**
     * Fill dialog request would likely be sent slightly later.
     */
@@ -1327,6 +1350,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        mPresentationStatsEventLogger = PresentationStatsEventLogger.forSessionId(sessionId);
        mFillRequestEventLogger = FillRequestEventLogger.forSessionId(sessionId);
        mFillResponseEventLogger = FillResponseEventLogger.forSessionId(sessionId);
        mSessionCommittedEventLogger = SessionCommittedEventLogger.forSessionId(sessionId);
        mSaveEventLogger = SaveEventLogger.forSessionId(sessionId);
        synchronized (mLock) {
            mSessionFlags = new SessionFlags();
            mSessionFlags.mAugmentedAutofillOnly = forAugmentedAutofillOnly;
@@ -2048,6 +2073,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
    @Override
    public void onSaveRequestSuccess(@NonNull String servicePackageName,
            @Nullable IntentSender intentSender) {
        // Log onSaveRequest result.
        mSaveEventLogger.maybeSetIsSaved(true);
        final long saveRequestFinishTimestamp = SystemClock.elapsedRealtime() - mLatencyBaseTime;
        mSaveEventLogger.maybeSetLatencySaveFinishMillis(saveRequestFinishTimestamp);
        mSaveEventLogger.logAndEndEvent();

        synchronized (mLock) {
            mSessionFlags.mShowingSaveUi = false;

@@ -2060,6 +2091,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName)
                .setType(intentSender == null ? MetricsEvent.TYPE_SUCCESS : MetricsEvent.TYPE_OPEN);
        mMetricsLogger.write(log);


        if (intentSender != null) {
            if (sDebug) Slog.d(TAG, "Starting intent sender on save()");
            startIntentSenderAndFinishSession(intentSender);
@@ -2074,6 +2107,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
    public void onSaveRequestFailure(@Nullable CharSequence message,
            @NonNull String servicePackageName) {
        boolean showMessage = !TextUtils.isEmpty(message);

        // Log onSaveRequest result.
        final long saveRequestFinishTimestamp = SystemClock.elapsedRealtime() - mLatencyBaseTime;
        mSaveEventLogger.maybeSetLatencySaveFinishMillis(saveRequestFinishTimestamp);
        mSaveEventLogger.logAndEndEvent();

        synchronized (mLock) {
            mSessionFlags.mShowingSaveUi = false;

@@ -2099,6 +2138,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        }
        mMetricsLogger.write(log);


        if (showMessage) {
            getUiForShowing().showError(message, this);
        }
@@ -2188,13 +2228,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
    // AutoFillUiCallback
    @Override
    public void save() {
        mSaveEventLogger.maybeSetSaveButtonClicked(true);
        synchronized (mLock) {
            if (mDestroyed) {
                Slog.w(TAG, "Call to Session#save() rejected - session: "
                        + id + " destroyed");
                mSaveEventLogger.logAndEndEvent();
                return;
            }
        }
        final long saveRequestStartTimestamp = SystemClock.elapsedRealtime() - mLatencyBaseTime;
        mSaveEventLogger.maybeSetLatencySaveRequestMillis(saveRequestStartTimestamp);
        mHandler.sendMessage(obtainMessage(
                AutofillManagerServiceImpl::handleSessionSave,
                mService, this));
@@ -2203,12 +2247,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
    // AutoFillUiCallback
    @Override
    public void cancelSave() {
        mSaveEventLogger.maybeSetDialogDismissed(true);
        synchronized (mLock) {
            mSessionFlags.mShowingSaveUi = false;

            if (mDestroyed) {
                Slog.w(TAG, "Call to Session#cancelSave() rejected - session: "
                        + id + " destroyed");
                mSaveEventLogger.logAndEndEvent();
                return;
            }
        }
@@ -3031,6 +3077,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        if (mDestroyed) {
            Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: "
                    + id + " destroyed");
            mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_SESSION_DESTROYED);
            mSaveEventLogger.logAndEndEvent();
            return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ false,
                    Event.NO_SAVE_UI_REASON_NONE);
        }
@@ -3050,6 +3098,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         */
        if (saveInfo == null) {
            if (sVerbose) Slog.v(TAG, "showSaveLocked(" + this.id + "): no saveInfo from service");
            mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_NO_SAVE_INFO);
            mSaveEventLogger.logAndEndEvent();
            return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
                    Event.NO_SAVE_UI_REASON_NO_SAVE_INFO);
        }
@@ -3057,6 +3107,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        if ((saveInfo.getFlags() & SaveInfo.FLAG_DELAY_SAVE) != 0) {
            // TODO(b/113281366): log metrics
            if (sDebug) Slog.v(TAG, "showSaveLocked(" + this.id + "): service asked to delay save");
            mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG);
            mSaveEventLogger.logAndEndEvent();
            return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ false,
                    Event.NO_SAVE_UI_REASON_WITH_DELAY_SAVE_FLAG);
        }
@@ -3130,6 +3182,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                                        + "didn't change: " + value);
                            }
                            changed = false;
                        } else {
                            mSaveEventLogger.maybeSetIsNewField(true);
                        }
                    } else {
                        isUpdate = true;
@@ -3153,6 +3207,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        int saveDialogNotShowReason;
        if (!allRequiredAreNotEmpty) {
            saveDialogNotShowReason = Event.NO_SAVE_UI_REASON_HAS_EMPTY_REQUIRED;

            mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_HAS_EMPTY_REQUIRED);
            mSaveEventLogger.logAndEndEvent();
        } else {
            // Must look up all optional ids in 2 scenarios:
            // - if no required id changed but an optional id did, it should trigger save / update
@@ -3188,6 +3245,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                            }
                            if (filledValue != null) {
                                isUpdate = true;
                            } else {
                                mSaveEventLogger.maybeSetIsNewField(true);
                            }
                            atLeastOneChanged = true;
                        }
@@ -3206,6 +3265,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
            }
            if (!atLeastOneChanged) {
                saveDialogNotShowReason = Event.NO_SAVE_UI_REASON_NO_VALUE_CHANGED;
                mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_NO_VALUE_CHANGED);
                mSaveEventLogger.logAndEndEvent();
            } else {
                if (sDebug) {
                    Slog.d(TAG, "at least one field changed, validate fields for save UI");
@@ -3224,6 +3285,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                        Slog.e(TAG, "Not showing save UI because validation failed:", e);
                        log.setType(MetricsEvent.TYPE_FAILURE);
                        mMetricsLogger.write(log);
                        mSaveEventLogger.maybeSetSaveUiNotShownReason(
                            NO_SAVE_REASON_FIELD_VALIDATION_FAILED);
                        mSaveEventLogger.logAndEndEvent();
                        return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
                                Event.NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED);
                    }
@@ -3231,6 +3295,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    mMetricsLogger.write(log);
                    if (!isValid) {
                        Slog.i(TAG, "not showing save UI because fields failed validation");
                        mSaveEventLogger.maybeSetSaveUiNotShownReason(
                            NO_SAVE_REASON_FIELD_VALIDATION_FAILED);
                        mSaveEventLogger.logAndEndEvent();
                        return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
                                Event.NO_SAVE_UI_REASON_FIELD_VALIDATION_FAILED);
                    }
@@ -3271,6 +3338,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                            Slog.d(TAG, "ignoring Save UI because all fields match contents of "
                                    + "dataset #" + i + ": " + dataset);
                        }
                        mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_DATASET_MATCH);
                        mSaveEventLogger.logAndEndEvent();
                        return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
                                Event.NO_SAVE_UI_REASON_DATASET_MATCH);
                    }
@@ -3292,14 +3361,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                }
                if (serviceLabel == null || serviceIcon == null) {
                    wtf(null, "showSaveLocked(): no service label or icon");
                    mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_NONE);
                    mSaveEventLogger.logAndEndEvent();
                    return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
                            Event.NO_SAVE_UI_REASON_NONE);
                }

                final long saveUiDisplayStartTimestamp = SystemClock.elapsedRealtime();
                getUiForShowing().showSaveUi(serviceLabel, serviceIcon,
                        mService.getServicePackageName(), saveInfo, this,
                        mComponentName, this, mPendingSaveUi, isUpdate, mCompatMode,
                        response.getShowSaveDialogIcon());
                mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis(
                    SystemClock.elapsedRealtime()- saveUiDisplayStartTimestamp);
                if (client != null) {
                    try {
                        client.setSaveUiState(id, true);
@@ -3471,11 +3544,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        if (mDestroyed) {
            Slog.w(TAG, "Call to Session#callSaveLocked() rejected - session: "
                    + id + " destroyed");
            mSaveEventLogger.maybeSetIsSaved(false);
            mSaveEventLogger.logAndEndEvent();
            return;
        }
        if (mRemoteFillService == null) {
            wtf(null, "callSaveLocked() called without a remote service. "
                    + "mForAugmentedAutofillOnly: %s", mSessionFlags.mAugmentedAutofillOnly);
            mSaveEventLogger.maybeSetIsSaved(false);
            mSaveEventLogger.logAndEndEvent();
            return;
        }

@@ -3483,6 +3560,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState

        if (mContexts == null) {
            Slog.w(TAG, "callSaveLocked(): no contexts");
            mSaveEventLogger.maybeSetIsSaved(false);
            mSaveEventLogger.logAndEndEvent();
            return;
        }

@@ -3899,6 +3978,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    mPresentationStatsEventLogger.maybeSetRequestId(response.getRequestId());
                    mPresentationStatsEventLogger.maybeSetAvailableCount(
                            response.getDatasets(), mCurrentViewId);
                    mFillResponseEventLogger.maybeSetAvailableCount(
                        response.getDatasets(), mCurrentViewId);
                }

                if (isSameViewEntered) {
@@ -4069,6 +4150,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
            if (mDestroyed) {
                Slog.w(TAG, "Call to Session#onFillReady() rejected - session: "
                        + id + " destroyed");
                mSaveEventLogger.maybeSetSaveUiNotShownReason(NO_SAVE_REASON_SESSION_DESTROYED);
                mSaveEventLogger.logAndEndEvent();
                mPresentationStatsEventLogger.maybeSetNoPresentationEventReason(
                    NOT_SHOWN_REASON_SESSION_COMMITTED_PREMATURELY);
                mPresentationStatsEventLogger.logAndEndEvent();
                return;
            }
        }
@@ -4100,7 +4186,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState

        synchronized (mLock) {
            // Time passed since Session was created
            long suggestionSentRelativeTimestamp =
            final long suggestionSentRelativeTimestamp =
                    SystemClock.elapsedRealtime() - mLatencyBaseTime;
            mPresentationStatsEventLogger.maybeSetSuggestionSentTimestampMs(
                    (int) (suggestionSentRelativeTimestamp));
@@ -4468,10 +4554,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
            saveTriggerId = saveInfo.getTriggerId();
            if (saveTriggerId != null) {
                writeLog(MetricsEvent.AUTOFILL_EXPLICIT_SAVE_TRIGGER_DEFINITION);
                mSaveEventLogger.maybeSetSaveUiShownReason(SAVE_UI_SHOWN_REASON_TRIGGER_ID_SET);
            }
            flags = saveInfo.getFlags();
            mSaveOnAllViewsInvisible = (flags & SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE) != 0;

            mFillResponseEventLogger.maybeSetSaveUiTriggerIds(HAVE_SAVE_TRIGGER_ID);

            // Start to log Save event.
            mSaveEventLogger.maybeSetRequestId(response.getRequestId());
            mSaveEventLogger.maybeSetAppPackageUid(uid);
            mSaveEventLogger.maybeSetSaveUiTriggerIds(HAVE_SAVE_TRIGGER_ID);
            mSaveEventLogger.maybeSetFlag(flags);

            // We only need to track views if we want to save once they become invisible.
            if (mSaveOnAllViewsInvisible) {
                if (trackedViews == null) {
@@ -4479,18 +4574,28 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                }
                if (saveInfo.getRequiredIds() != null) {
                    Collections.addAll(trackedViews, saveInfo.getRequiredIds());
                    mSaveEventLogger.maybeSetSaveUiShownReason(
                        SAVE_UI_SHOWN_REASON_REQUIRED_ID_CHANGE);
                }

                if (saveInfo.getOptionalIds() != null) {
                    Collections.addAll(trackedViews, saveInfo.getOptionalIds());
                    mSaveEventLogger.maybeSetSaveUiShownReason(
                        SAVE_UI_SHOWN_REASON_OPTIONAL_ID_CHANGE);
                }
            }
            if ((flags & SaveInfo.FLAG_DONT_SAVE_ON_FINISH) != 0) {
                mSaveEventLogger.maybeSetSaveUiShownReason(
                    SAVE_UI_SHOWN_REASON_UNKNOWN);
                mSaveEventLogger.maybeSetSaveUiNotShownReason(
                    NO_SAVE_REASON_WITH_DONT_SAVE_ON_FINISH_FLAG);
                saveOnFinish = false;
            }

        } else {
            flags = 0;
            mSaveEventLogger.maybeSetSaveUiNotShownReason(
                NO_SAVE_REASON_NO_SAVE_INFO);
            saveTriggerId = null;
        }