Add the reason why a save dialog was not shown to FillEventHistory.
In order to provide a better user experience, it would better know the
reason why a save dialog was not shown and improve the autofill experience.
So it is necessary to add the reason why a save dialog was not shown to
FillEventHistory.
Bug: 158328375
Test: atest FillEventHistoryTest
Test: atest InlineFillEventHistoryTest
Change-Id: I50c1e40334066d3f4844426c4b03294079a967b2
diff --git a/api/current.txt b/api/current.txt
index 9b9e258..11ca10c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -43168,8 +43168,16 @@
method @NonNull public java.util.Map<android.view.autofill.AutofillId,android.service.autofill.FieldClassification> getFieldsClassification();
method @NonNull public java.util.Set<java.lang.String> getIgnoredDatasetIds();
method @NonNull public java.util.Map<android.view.autofill.AutofillId,java.util.Set<java.lang.String>> getManuallyEnteredField();
+ method public int getNoSaveReason();
method @NonNull public java.util.Set<java.lang.String> getSelectedDatasetIds();
method public int getType();
+ field public static final int NO_SAVE_REASON_DATASET_MATCH = 6; // 0x6
+ field public static final int NO_SAVE_REASON_FIELD_VALIDATION_FAILED = 5; // 0x5
+ field public static final int NO_SAVE_REASON_HAS_EMPTY_REQUIRED = 3; // 0x3
+ field public static final int NO_SAVE_REASON_NONE = 0; // 0x0
+ field public static final int NO_SAVE_REASON_NO_SAVE_INFO = 1; // 0x1
+ field public static final int NO_SAVE_REASON_NO_VALUE_CHANGED = 4; // 0x4
+ field public static final int NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG = 2; // 0x2
field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
field public static final int TYPE_CONTEXT_COMMITTED = 4; // 0x4
field public static final int TYPE_DATASETS_SHOWN = 5; // 0x5
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index 1cd2d62..f226528 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -159,6 +159,7 @@
FieldClassification.writeArrayToParcel(parcel,
event.mDetectedFieldClassifications);
}
+ parcel.writeInt(event.mSaveDialogNotShowReason);
}
}
}
@@ -243,6 +244,40 @@
@Retention(RetentionPolicy.SOURCE)
@interface EventIds{}
+ /** No reason for save dialog. */
+ public static final int NO_SAVE_REASON_NONE = 0;
+
+ /** The SaveInfo associated with the FillResponse is null. */
+ public static final int NO_SAVE_REASON_NO_SAVE_INFO = 1;
+
+ /** The service asked to delay save. */
+ public static final int NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG = 2;
+
+ /** There was empty value for required ids. */
+ public static final int NO_SAVE_REASON_HAS_EMPTY_REQUIRED = 3;
+
+ /** No value has been changed. */
+ public static final int NO_SAVE_REASON_NO_VALUE_CHANGED = 4;
+
+ /** Fields failed validation. */
+ public static final int NO_SAVE_REASON_FIELD_VALIDATION_FAILED = 5;
+
+ /** All fields matched contents of datasets. */
+ public static final int NO_SAVE_REASON_DATASET_MATCH = 6;
+
+ /** @hide */
+ @IntDef(prefix = { "NO_SAVE_REASON_" }, value = {
+ NO_SAVE_REASON_NONE,
+ NO_SAVE_REASON_NO_SAVE_INFO,
+ NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG,
+ NO_SAVE_REASON_HAS_EMPTY_REQUIRED,
+ NO_SAVE_REASON_NO_VALUE_CHANGED,
+ NO_SAVE_REASON_FIELD_VALIDATION_FAILED,
+ NO_SAVE_REASON_DATASET_MATCH
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NoSaveReason{}
+
@EventIds private final int mEventType;
@Nullable private final String mDatasetId;
@Nullable private final Bundle mClientState;
@@ -261,6 +296,8 @@
@Nullable private final AutofillId[] mDetectedFieldIds;
@Nullable private final FieldClassification[] mDetectedFieldClassifications;
+ @NoSaveReason private final int mSaveDialogNotShowReason;
+
/**
* Returns the type of the event.
*
@@ -448,6 +485,18 @@
}
/**
+ * Returns the reason why a save dialog was not shown.
+ *
+ * <p><b>Note: </b>Only set on events of type {@link #TYPE_CONTEXT_COMMITTED}. For the other
+ * event types, the reason is set to NO_SAVE_REASON_NONE.
+ *
+ * @return The reason why a save dialog was not shown.
+ */
+ public int getNoSaveReason() {
+ return mSaveDialogNotShowReason;
+ }
+
+ /**
* Creates a new event.
*
* @param eventType The type of the event
@@ -481,6 +530,48 @@
@Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
@Nullable AutofillId[] detectedFieldIds,
@Nullable FieldClassification[] detectedFieldClassifications) {
+ this(eventType, datasetId, clientState, selectedDatasetIds, ignoredDatasetIds,
+ changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
+ manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications,
+ NO_SAVE_REASON_NONE);
+ }
+
+ /**
+ * Creates a new event.
+ *
+ * @param eventType The type of the event
+ * @param datasetId The dataset the event was on, or {@code null} if the event was on the
+ * whole response.
+ * @param clientState The client state associated with the event.
+ * @param selectedDatasetIds The ids of datasets selected by the user.
+ * @param ignoredDatasetIds The ids of datasets NOT select by the user.
+ * @param changedFieldIds The ids of fields changed by the user.
+ * @param changedDatasetIds The ids of the datasets that havd values matching the
+ * respective entry on {@code changedFieldIds}.
+ * @param manuallyFilledFieldIds The ids of fields that were manually entered by the user
+ * and belonged to datasets.
+ * @param manuallyFilledDatasetIds The ids of datasets that had values matching the
+ * respective entry on {@code manuallyFilledFieldIds}.
+ * @param detectedFieldClassifications the field classification matches.
+ * @param saveDialogNotShowReason The reason why a save dialog was not shown.
+ *
+ * @throws IllegalArgumentException If the length of {@code changedFieldIds} and
+ * {@code changedDatasetIds} doesn't match.
+ * @throws IllegalArgumentException If the length of {@code manuallyFilledFieldIds} and
+ * {@code manuallyFilledDatasetIds} doesn't match.
+ *
+ * @hide
+ */
+ public Event(int eventType, @Nullable String datasetId, @Nullable Bundle clientState,
+ @Nullable List<String> selectedDatasetIds,
+ @Nullable ArraySet<String> ignoredDatasetIds,
+ @Nullable ArrayList<AutofillId> changedFieldIds,
+ @Nullable ArrayList<String> changedDatasetIds,
+ @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
+ @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
+ @Nullable AutofillId[] detectedFieldIds,
+ @Nullable FieldClassification[] detectedFieldClassifications,
+ int saveDialogNotShowReason) {
mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN,
"eventType");
mDatasetId = datasetId;
@@ -506,6 +597,10 @@
mDetectedFieldIds = detectedFieldIds;
mDetectedFieldClassifications = detectedFieldClassifications;
+
+ mSaveDialogNotShowReason = Preconditions.checkArgumentInRange(saveDialogNotShowReason,
+ NO_SAVE_REASON_NONE, NO_SAVE_REASON_DATASET_MATCH,
+ "saveDialogNotShowReason");
}
@Override
@@ -521,6 +616,7 @@
+ ", detectedFieldIds=" + Arrays.toString(mDetectedFieldIds)
+ ", detectedFieldClassifications ="
+ Arrays.toString(mDetectedFieldClassifications)
+ + ", saveDialogNotShowReason=" + mSaveDialogNotShowReason
+ "]";
}
}
@@ -562,12 +658,14 @@
(detectedFieldIds != null)
? FieldClassification.readArrayFromParcel(parcel)
: null;
+ final int saveDialogNotShowReason = parcel.readInt();
selection.addEvent(new Event(eventType, datasetId, clientState,
selectedDatasetIds, ignoredDatasets,
changedFieldIds, changedDatasetIds,
manuallyFilledFieldIds, manuallyFilledDatasetIds,
- detectedFieldIds, detectedFieldClassifications));
+ detectedFieldIds, detectedFieldClassifications,
+ saveDialogNotShowReason));
}
return selection;
}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index d62e132..ff301b6 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -41311,8 +41311,16 @@
method @NonNull public java.util.Map<android.view.autofill.AutofillId,android.service.autofill.FieldClassification> getFieldsClassification();
method @NonNull public java.util.Set<java.lang.String> getIgnoredDatasetIds();
method @NonNull public java.util.Map<android.view.autofill.AutofillId,java.util.Set<java.lang.String>> getManuallyEnteredField();
+ method public int getNoSaveReason();
method @NonNull public java.util.Set<java.lang.String> getSelectedDatasetIds();
method public int getType();
+ field public static final int NO_SAVE_REASON_DATASET_MATCH = 6; // 0x6
+ field public static final int NO_SAVE_REASON_FIELD_VALIDATION_FAILED = 5; // 0x5
+ field public static final int NO_SAVE_REASON_HAS_EMPTY_REQUIRED = 3; // 0x3
+ field public static final int NO_SAVE_REASON_NONE = 0; // 0x0
+ field public static final int NO_SAVE_REASON_NO_SAVE_INFO = 1; // 0x1
+ field public static final int NO_SAVE_REASON_NO_VALUE_CHANGED = 4; // 0x4
+ field public static final int NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG = 2; // 0x2
field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
field public static final int TYPE_CONTEXT_COMMITTED = 4; // 0x4
field public static final int TYPE_DATASETS_SHOWN = 5; // 0x5
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 57ffe04..a6b82f4 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -55,6 +55,7 @@
import android.service.autofill.FieldClassification.Match;
import android.service.autofill.FillEventHistory;
import android.service.autofill.FillEventHistory.Event;
+import android.service.autofill.FillEventHistory.Event.NoSaveReason;
import android.service.autofill.FillResponse;
import android.service.autofill.IAutoFillService;
import android.service.autofill.InlineSuggestionRenderService;
@@ -429,9 +430,15 @@
return;
}
- session.logContextCommitted();
+ final Session.SaveResult saveResult = session.showSaveLocked();
- final boolean finished = session.showSaveLocked();
+ session.logContextCommitted(saveResult.getNoSaveReason());
+
+ if (saveResult.isLogSaveShown()) {
+ session.logSaveUiShown();
+ }
+
+ final boolean finished = saveResult.isRemoveSession();
if (sVerbose) Slog.v(TAG, "finishSessionLocked(): session finished on save? " + finished);
if (finished) {
@@ -868,7 +875,9 @@
@NonNull ComponentName appComponentName, boolean compatMode) {
logContextCommittedLocked(sessionId, clientState, selectedDatasets, ignoredDatasets,
changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
- manuallyFilledDatasetIds, null, null, appComponentName, compatMode);
+ manuallyFilledDatasetIds, /* detectedFieldIdsList= */ null,
+ /* detectedFieldClassificationsList= */ null, appComponentName, compatMode,
+ Event.NO_SAVE_REASON_NONE);
}
@GuardedBy("mLock")
@@ -881,7 +890,8 @@
@Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
@Nullable ArrayList<AutofillId> detectedFieldIdsList,
@Nullable ArrayList<FieldClassification> detectedFieldClassificationsList,
- @NonNull ComponentName appComponentName, boolean compatMode) {
+ @NonNull ComponentName appComponentName, boolean compatMode,
+ @NoSaveReason int saveDialogNotShowReason) {
if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
if (sVerbose) {
Slog.v(TAG, "logContextCommitted() with FieldClassification: id=" + sessionId
@@ -893,7 +903,8 @@
+ ", detectedFieldIds=" + detectedFieldIdsList
+ ", detectedFieldClassifications=" + detectedFieldClassificationsList
+ ", appComponentName=" + appComponentName.toShortString()
- + ", compatMode=" + compatMode);
+ + ", compatMode=" + compatMode
+ + ", saveDialogNotShowReason=" + saveDialogNotShowReason);
}
AutofillId[] detectedFieldsIds = null;
FieldClassification[] detectedFieldClassifications = null;
@@ -929,7 +940,7 @@
clientState, selectedDatasets, ignoredDatasets,
changedFieldIds, changedDatasetIds,
manuallyFilledFieldIds, manuallyFilledDatasetIds,
- detectedFieldsIds, detectedFieldClassifications));
+ detectedFieldsIds, detectedFieldClassifications, saveDialogNotShowReason));
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 1970b57..0e2eef8 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -71,6 +71,8 @@
import android.service.autofill.FieldClassification.Match;
import android.service.autofill.FieldClassificationUserData;
import android.service.autofill.FillContext;
+import android.service.autofill.FillEventHistory.Event;
+import android.service.autofill.FillEventHistory.Event.NoSaveReason;
import android.service.autofill.FillRequest;
import android.service.autofill.FillResponse;
import android.service.autofill.InlinePresentation;
@@ -1596,10 +1598,22 @@
* when necessary.
*/
public void logContextCommitted() {
- mHandler.sendMessage(obtainMessage(Session::handleLogContextCommitted, this));
+ mHandler.sendMessage(obtainMessage(Session::handleLogContextCommitted, this,
+ Event.NO_SAVE_REASON_NONE));
}
- private void handleLogContextCommitted() {
+ /**
+ * Generates a {@link android.service.autofill.FillEventHistory.Event#TYPE_CONTEXT_COMMITTED}
+ * when necessary.
+ *
+ * @param saveDialogNotShowReason The reason why a save dialog was not shown.
+ */
+ public void logContextCommitted(@NoSaveReason int saveDialogNotShowReason) {
+ mHandler.sendMessage(obtainMessage(Session::handleLogContextCommitted, this,
+ saveDialogNotShowReason));
+ }
+
+ private void handleLogContextCommitted(@NoSaveReason int saveDialogNotShowReason) {
final FillResponse lastResponse;
synchronized (mLock) {
lastResponse = getLastResponseLocked("logContextCommited(%s)");
@@ -1629,22 +1643,25 @@
// Sets field classification scores
if (userData != null && fcStrategy != null) {
- logFieldClassificationScore(fcStrategy, userData);
+ logFieldClassificationScore(fcStrategy, userData, saveDialogNotShowReason);
} else {
- logContextCommitted(null, null);
+ logContextCommitted(null, null, saveDialogNotShowReason);
}
}
private void logContextCommitted(@Nullable ArrayList<AutofillId> detectedFieldIds,
- @Nullable ArrayList<FieldClassification> detectedFieldClassifications) {
+ @Nullable ArrayList<FieldClassification> detectedFieldClassifications,
+ @NoSaveReason int saveDialogNotShowReason) {
synchronized (mLock) {
- logContextCommittedLocked(detectedFieldIds, detectedFieldClassifications);
+ logContextCommittedLocked(detectedFieldIds, detectedFieldClassifications,
+ saveDialogNotShowReason);
}
}
@GuardedBy("mLock")
private void logContextCommittedLocked(@Nullable ArrayList<AutofillId> detectedFieldIds,
- @Nullable ArrayList<FieldClassification> detectedFieldClassifications) {
+ @Nullable ArrayList<FieldClassification> detectedFieldClassifications,
+ @NoSaveReason int saveDialogNotShowReason) {
final FillResponse lastResponse = getLastResponseLocked("logContextCommited(%s)");
if (lastResponse == null) return;
@@ -1822,10 +1839,10 @@
}
}
- mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
- ignoredDatasets, changedFieldIds, changedDatasetIds,
- manuallyFilledFieldIds, manuallyFilledDatasetIds, detectedFieldIds,
- detectedFieldClassifications, mComponentName, mCompatMode);
+ mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds, ignoredDatasets,
+ changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
+ manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications,
+ mComponentName, mCompatMode, saveDialogNotShowReason);
}
/**
@@ -1833,7 +1850,8 @@
* {@code fieldId} based on its {@code currentValue} and {@code userData}.
*/
private void logFieldClassificationScore(@NonNull FieldClassificationStrategy fcStrategy,
- @NonNull FieldClassificationUserData userData) {
+ @NonNull FieldClassificationUserData userData,
+ @NoSaveReason int saveDialogNotShowReason) {
final String[] userValues = userData.getValues();
final String[] categoryIds = userData.getCategoryIds();
@@ -1879,7 +1897,7 @@
final RemoteCallback callback = new RemoteCallback((result) -> {
if (result == null) {
if (sDebug) Slog.d(TAG, "setFieldClassificationScore(): no results");
- logContextCommitted(null, null);
+ logContextCommitted(null, null, saveDialogNotShowReason);
return;
}
final Scores scores = result.getParcelable(EXTRA_SCORES);
@@ -1940,7 +1958,8 @@
return;
}
- logContextCommitted(detectedFieldIds, detectedFieldClassifications);
+ logContextCommitted(detectedFieldIds, detectedFieldClassifications,
+ saveDialogNotShowReason);
});
fcStrategy.calculateScores(callback, currentValues, userValues, categoryIds,
@@ -1948,17 +1967,28 @@
}
/**
+ * Generates a {@link android.service.autofill.FillEventHistory.Event#TYPE_SAVE_SHOWN}
+ * when necessary.
+ *
+ * <p>Note: It is necessary to call logContextCommitted() first before calling this method.
+ */
+ public void logSaveUiShown() {
+ mHandler.sendMessage(obtainMessage(Session::logSaveShown, this));
+ }
+
+ /**
* Shows the save UI, when session can be saved.
*
- * @return {@code true} if session is done and could be removed, or {@code false} if it's
- * pending user action or the service asked to keep it alive (for multi-screens workflow).
+ * @return {@link SaveResult} that contains the save ui display status information.
*/
@GuardedBy("mLock")
- public boolean showSaveLocked() {
+ @NonNull
+ public SaveResult showSaveLocked() {
if (mDestroyed) {
Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: "
+ id + " destroyed");
- return false;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ false,
+ Event.NO_SAVE_REASON_NONE);
}
final FillResponse response = getLastResponseLocked("showSaveLocked(%s)");
final SaveInfo saveInfo = response == null ? null : response.getSaveInfo();
@@ -1975,13 +2005,15 @@
*/
if (saveInfo == null) {
if (sVerbose) Slog.v(TAG, "showSaveLocked(" + this.id + "): no saveInfo from service");
- return true;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
+ Event.NO_SAVE_REASON_NO_SAVE_INFO);
}
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");
- return false;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ false,
+ Event.NO_SAVE_REASON_WITH_DELAY_SAVE_FLAG);
}
final ArrayMap<AutofillId, InternalSanitizer> sanitizers = createSanitizers(saveInfo);
@@ -2073,7 +2105,10 @@
Slog.v(TAG, "allRequiredAreNotEmpty: " + allRequiredAreNotEmpty + " hasOptional: "
+ (optionalIds != null));
}
- if (allRequiredAreNotEmpty) {
+ int saveDialogNotShowReason;
+ if (!allRequiredAreNotEmpty) {
+ saveDialogNotShowReason = Event.NO_SAVE_REASON_HAS_EMPTY_REQUIRED;
+ } 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
// - if at least one required id changed but it was not part of a filled dataset, we
@@ -2124,7 +2159,9 @@
}
}
}
- if (atLeastOneChanged) {
+ if (!atLeastOneChanged) {
+ saveDialogNotShowReason = Event.NO_SAVE_REASON_NO_VALUE_CHANGED;
+ } else {
if (sDebug) {
Slog.d(TAG, "at least one field changed, validate fields for save UI");
}
@@ -2142,13 +2179,15 @@
Slog.e(TAG, "Not showing save UI because validation failed:", e);
log.setType(MetricsEvent.TYPE_FAILURE);
mMetricsLogger.write(log);
- return true;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
+ Event.NO_SAVE_REASON_FIELD_VALIDATION_FAILED);
}
mMetricsLogger.write(log);
if (!isValid) {
Slog.i(TAG, "not showing save UI because fields failed validation");
- return true;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
+ Event.NO_SAVE_REASON_FIELD_VALIDATION_FAILED);
}
}
@@ -2187,7 +2226,8 @@
Slog.d(TAG, "ignoring Save UI because all fields match contents of "
+ "dataset #" + i + ": " + dataset);
}
- return true;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
+ Event.NO_SAVE_REASON_DATASET_MATCH);
}
}
@@ -2196,9 +2236,6 @@
+ id + "!");
}
- // Use handler so logContextCommitted() is logged first
- mHandler.sendMessage(obtainMessage(Session::logSaveShown, this));
-
final IAutoFillManagerClient client = getClient();
mPendingSaveUi = new PendingUi(new Binder(), id, client);
@@ -2210,8 +2247,10 @@
}
if (serviceLabel == null || serviceIcon == null) {
wtf(null, "showSaveLocked(): no service label or icon");
- return true;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
+ Event.NO_SAVE_REASON_NONE);
}
+
getUiForShowing().showSaveUi(serviceLabel, serviceIcon,
mService.getServicePackageName(), saveInfo, this,
mComponentName, this, mPendingSaveUi, isUpdate, mCompatMode);
@@ -2223,7 +2262,8 @@
}
}
mIsSaving = true;
- return false;
+ return new SaveResult(/* logSaveShown= */ true, /* removeSession= */ false,
+ Event.NO_SAVE_REASON_NONE);
}
}
// Nothing changed...
@@ -2232,7 +2272,8 @@
+ "allRequiredAreNotNull=" + allRequiredAreNotEmpty
+ ", atLeastOneChanged=" + atLeastOneChanged);
}
- return true;
+ return new SaveResult(/* logSaveShown= */ false, /* removeSession= */ true,
+ saveDialogNotShowReason);
}
private void logSaveShown() {
@@ -3586,6 +3627,97 @@
}
}
+ /**
+ * The result of checking whether to show the save dialog, when session can be saved.
+ *
+ * @hide
+ */
+ static final class SaveResult {
+ /**
+ * Whether to record the save dialog has been shown.
+ */
+ private boolean mLogSaveShown;
+
+ /**
+ * Whether to remove the session.
+ */
+ private boolean mRemoveSession;
+
+ /**
+ * The reason why a save dialog was not shown.
+ */
+ @NoSaveReason private int mSaveDialogNotShowReason;
+
+ SaveResult(boolean logSaveShown, boolean removeSession,
+ @NoSaveReason int saveDialogNotShowReason) {
+ mLogSaveShown = logSaveShown;
+ mRemoveSession = removeSession;
+ mSaveDialogNotShowReason = saveDialogNotShowReason;
+ }
+
+ /**
+ * Returns whether to record the save dialog has been shown.
+ *
+ * @return Whether to record the save dialog has been shown.
+ */
+ public boolean isLogSaveShown() {
+ return mLogSaveShown;
+ }
+
+ /**
+ * Sets whether to record the save dialog has been shown.
+ *
+ * @param logSaveShown Whether to record the save dialog has been shown.
+ */
+ public void setLogSaveShown(boolean logSaveShown) {
+ mLogSaveShown = logSaveShown;
+ }
+
+ /**
+ * Returns whether to remove the session.
+ *
+ * @return Whether to remove the session.
+ */
+ public boolean isRemoveSession() {
+ return mRemoveSession;
+ }
+
+ /**
+ * Sets whether to remove the session.
+ *
+ * @param removeSession Whether to remove the session.
+ */
+ public void setRemoveSession(boolean removeSession) {
+ mRemoveSession = removeSession;
+ }
+
+ /**
+ * Returns the reason why a save dialog was not shown.
+ *
+ * @return The reason why a save dialog was not shown.
+ */
+ @NoSaveReason
+ public int getNoSaveReason() {
+ return mSaveDialogNotShowReason;
+ }
+
+ /**
+ * Sets the reason why a save dialog was not shown.
+ *
+ * @param saveDialogNotShowReason The reason why a save dialog was not shown.
+ */
+ public void setSaveDialogNotShowReason(@NoSaveReason int saveDialogNotShowReason) {
+ mSaveDialogNotShowReason = saveDialogNotShowReason;
+ }
+
+ @Override
+ public String toString() {
+ return "SaveResult: [logSaveShown=" + mLogSaveShown
+ + ", removeSession=" + mRemoveSession
+ + ", saveDialogNotShowReason=" + mSaveDialogNotShowReason + "]";
+ }
+ }
+
@Override
public String toString() {
return "Session: [id=" + id + ", component=" + mComponentName + "]";