Merge "Reset Autofill dialog if the content is changed" into tm-qpr-dev

This commit is contained in:
Joanne Chung
2022-12-15 14:01:22 +00:00
committed by Android (Google) Code Review
3 changed files with 221 additions and 95 deletions

View File

@@ -111,6 +111,12 @@ public final class FillRequest implements Parcelable {
*/
public static final @RequestFlags int FLAG_IME_SHOWING = 0x80;
/**
* Indicates whether autofill session should reset the fill dialog state.
* @hide
*/
public static final @RequestFlags int FLAG_RESET_FILL_DIALOG_STATE = 0x100;
/** @hide */
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
@@ -208,7 +214,8 @@ public final class FillRequest implements Parcelable {
FLAG_PASSWORD_INPUT_TYPE,
FLAG_VIEW_NOT_FOCUSED,
FLAG_SUPPORTS_FILL_DIALOG,
FLAG_IME_SHOWING
FLAG_IME_SHOWING,
FLAG_RESET_FILL_DIALOG_STATE
})
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
@@ -236,6 +243,8 @@ public final class FillRequest implements Parcelable {
return "FLAG_SUPPORTS_FILL_DIALOG";
case FLAG_IME_SHOWING:
return "FLAG_IME_SHOWING";
case FLAG_RESET_FILL_DIALOG_STATE:
return "FLAG_RESET_FILL_DIALOG_STATE";
default: return Integer.toHexString(value);
}
}
@@ -312,7 +321,8 @@ public final class FillRequest implements Parcelable {
| FLAG_PASSWORD_INPUT_TYPE
| FLAG_VIEW_NOT_FOCUSED
| FLAG_SUPPORTS_FILL_DIALOG
| FLAG_IME_SHOWING);
| FLAG_IME_SHOWING
| FLAG_RESET_FILL_DIALOG_STATE);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
this.mDelayedFillIntentSender = delayedFillIntentSender;
@@ -473,7 +483,8 @@ public final class FillRequest implements Parcelable {
| FLAG_PASSWORD_INPUT_TYPE
| FLAG_VIEW_NOT_FOCUSED
| FLAG_SUPPORTS_FILL_DIALOG
| FLAG_IME_SHOWING);
| FLAG_IME_SHOWING
| FLAG_RESET_FILL_DIALOG_STATE);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
this.mDelayedFillIntentSender = delayedFillIntentSender;
@@ -495,10 +506,10 @@ public final class FillRequest implements Parcelable {
};
@DataClass.Generated(
time = 1647856966565L,
time = 1663290803064L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_RESET_FILL_DIALOG_STATE\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
@Deprecated
private void __metadata() {}

View File

@@ -19,6 +19,7 @@ package android.view.autofill;
import static android.service.autofill.FillRequest.FLAG_IME_SHOWING;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
import static android.service.autofill.FillRequest.FLAG_RESET_FILL_DIALOG_STATE;
import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
import static android.view.ContentInfo.SOURCE_AUTOFILL;
@@ -715,7 +716,7 @@ public final class AutofillManager {
* Autofill will automatically trigger a fill request after activity
* start if there is any field is autofillable. But if there is a field that
* triggered autofill, it is unnecessary to trigger again through
* AutofillManager#notifyViewEnteredForActivityStarted.
* AutofillManager#notifyViewEnteredForFillDialog.
*/
private AtomicBoolean mIsFillRequested;
@@ -728,6 +729,10 @@ public final class AutofillManager {
private final String[] mFillDialogEnabledHints;
// Tracked all views that have appeared, including views that there are no
// dataset in responses. Used to avoid request pre-fill request again and again.
private final ArraySet<AutofillId> mAllTrackedViews = new ArraySet<>();
/** @hide */
public interface AutofillClient {
/**
@@ -1173,6 +1178,16 @@ public final class AutofillManager {
* @hide
*/
public void notifyViewEnteredForFillDialog(View v) {
synchronized (mLock) {
if (mTrackedViews != null) {
// To support the fill dialog can show for the autofillable Views in
// different pages but in the same Activity. We need to reset the
// mIsFillRequested flag to allow asking for a new FillRequest when
// user switches to other page
mTrackedViews.checkViewState(v.getAutofillId());
}
}
// Skip if the fill request has been performed for a view.
if (mIsFillRequested.get()) {
return;
@@ -1299,6 +1314,10 @@ public final class AutofillManager {
}
mForAugmentedAutofillOnly = false;
}
if ((flags & FLAG_SUPPORTS_FILL_DIALOG) != 0) {
flags |= FLAG_RESET_FILL_DIALOG_STATE;
}
updateSessionLocked(id, null, value, ACTION_VIEW_ENTERED, flags);
}
addEnteredIdLocked(id);
@@ -2165,6 +2184,7 @@ public final class AutofillManager {
mIsFillRequested.set(false);
mShowAutofillDialogCalled = false;
mFillDialogTriggerIds = null;
mAllTrackedViews.clear();
if (resetEnteredIds) {
mEnteredIds = null;
}
@@ -2702,14 +2722,9 @@ public final class AutofillManager {
+ ", mFillableIds=" + mFillableIds
+ ", mEnabled=" + mEnabled
+ ", mSessionId=" + mSessionId);
}
if (mEnabled && mSessionId == sessionId) {
if (saveOnAllViewsInvisible) {
mTrackedViews = new TrackedViews(trackedIds);
} else {
mTrackedViews = null;
}
mSaveOnFinish = saveOnFinish;
if (fillableIds != null) {
if (mFillableIds == null) {
@@ -2731,6 +2746,27 @@ public final class AutofillManager {
mSaveTriggerId = saveTriggerId;
setNotifyOnClickLocked(mSaveTriggerId, true);
}
if (!saveOnAllViewsInvisible) {
trackedIds = null;
}
final ArraySet<AutofillId> allFillableIds = new ArraySet<>();
if (mFillableIds != null) {
allFillableIds.addAll(mFillableIds);
}
if (trackedIds != null) {
for (AutofillId id : trackedIds) {
id.resetSessionId();
allFillableIds.add(id);
}
}
if (!allFillableIds.isEmpty()) {
mTrackedViews = new TrackedViews(trackedIds, Helper.toArray(allFillableIds));
} else {
mTrackedViews = null;
}
}
}
}
@@ -3502,10 +3538,19 @@ public final class AutofillManager {
*/
private class TrackedViews {
/** Visible tracked views */
@Nullable private ArraySet<AutofillId> mVisibleTrackedIds;
@NonNull private final ArraySet<AutofillId> mVisibleTrackedIds;
/** Invisible tracked views */
@Nullable private ArraySet<AutofillId> mInvisibleTrackedIds;
@NonNull private final ArraySet<AutofillId> mInvisibleTrackedIds;
/** Visible tracked views for fill dialog */
@NonNull private final ArraySet<AutofillId> mVisibleDialogTrackedIds;
/** Invisible tracked views for fill dialog */
@NonNull private final ArraySet<AutofillId> mInvisibleDialogTrackedIds;
boolean mHasNewTrackedView;
boolean mIsTrackedSaveView;
/**
* Check if set is null or value is in set.
@@ -3571,43 +3616,65 @@ public final class AutofillManager {
*
* @param trackedIds The views to be tracked
*/
TrackedViews(@Nullable AutofillId[] trackedIds) {
final AutofillClient client = getClient();
if (!ArrayUtils.isEmpty(trackedIds) && client != null) {
final boolean[] isVisible;
TrackedViews(@Nullable AutofillId[] trackedIds, @Nullable AutofillId[] allTrackedIds) {
mVisibleTrackedIds = new ArraySet<>();
mInvisibleTrackedIds = new ArraySet<>();
if (!ArrayUtils.isEmpty(trackedIds)) {
mIsTrackedSaveView = true;
initialTrackedViews(trackedIds, mVisibleTrackedIds, mInvisibleTrackedIds);
}
if (client.autofillClientIsVisibleForAutofill()) {
if (sVerbose) Log.v(TAG, "client is visible, check tracked ids");
isVisible = client.autofillClientGetViewVisibility(trackedIds);
} else {
// All false
isVisible = new boolean[trackedIds.length];
}
final int numIds = trackedIds.length;
for (int i = 0; i < numIds; i++) {
final AutofillId id = trackedIds[i];
id.resetSessionId();
if (isVisible[i]) {
mVisibleTrackedIds = addToSet(mVisibleTrackedIds, id);
} else {
mInvisibleTrackedIds = addToSet(mInvisibleTrackedIds, id);
}
}
mVisibleDialogTrackedIds = new ArraySet<>();
mInvisibleDialogTrackedIds = new ArraySet<>();
if (!ArrayUtils.isEmpty(allTrackedIds)) {
initialTrackedViews(allTrackedIds, mVisibleDialogTrackedIds,
mInvisibleDialogTrackedIds);
mAllTrackedViews.addAll(Arrays.asList(allTrackedIds));
}
if (sVerbose) {
Log.v(TAG, "TrackedViews(trackedIds=" + Arrays.toString(trackedIds) + "): "
+ " mVisibleTrackedIds=" + mVisibleTrackedIds
+ " mInvisibleTrackedIds=" + mInvisibleTrackedIds);
+ " mInvisibleTrackedIds=" + mInvisibleTrackedIds
+ " allTrackedIds=" + Arrays.toString(allTrackedIds)
+ " mVisibleDialogTrackedIds=" + mVisibleDialogTrackedIds
+ " mInvisibleDialogTrackedIds=" + mInvisibleDialogTrackedIds);
}
if (mVisibleTrackedIds == null) {
if (mIsTrackedSaveView && mVisibleTrackedIds.isEmpty()) {
finishSessionLocked(/* commitReason= */ COMMIT_REASON_VIEW_CHANGED);
}
}
private void initialTrackedViews(AutofillId[] trackedIds,
@NonNull ArraySet<AutofillId> visibleSet,
@NonNull ArraySet<AutofillId> invisibleSet) {
final boolean[] isVisible;
final AutofillClient client = getClient();
if (ArrayUtils.isEmpty(trackedIds) || client == null) {
return;
}
if (client.autofillClientIsVisibleForAutofill()) {
if (sVerbose) Log.v(TAG, "client is visible, check tracked ids");
isVisible = client.autofillClientGetViewVisibility(trackedIds);
} else {
// All false
isVisible = new boolean[trackedIds.length];
}
final int numIds = trackedIds.length;
for (int i = 0; i < numIds; i++) {
final AutofillId id = trackedIds[i];
id.resetSessionId();
if (isVisible[i]) {
addToSet(visibleSet, id);
} else {
addToSet(invisibleSet, id);
}
}
}
/**
* Called when a {@link View view's} visibility changes.
*
@@ -3624,22 +3691,37 @@ public final class AutofillManager {
if (isClientVisibleForAutofillLocked()) {
if (isVisible) {
if (isInSet(mInvisibleTrackedIds, id)) {
mInvisibleTrackedIds = removeFromSet(mInvisibleTrackedIds, id);
mVisibleTrackedIds = addToSet(mVisibleTrackedIds, id);
removeFromSet(mInvisibleTrackedIds, id);
addToSet(mVisibleTrackedIds, id);
}
if (isInSet(mInvisibleDialogTrackedIds, id)) {
removeFromSet(mInvisibleDialogTrackedIds, id);
addToSet(mVisibleDialogTrackedIds, id);
}
} else {
if (isInSet(mVisibleTrackedIds, id)) {
mVisibleTrackedIds = removeFromSet(mVisibleTrackedIds, id);
mInvisibleTrackedIds = addToSet(mInvisibleTrackedIds, id);
removeFromSet(mVisibleTrackedIds, id);
addToSet(mInvisibleTrackedIds, id);
}
if (isInSet(mVisibleDialogTrackedIds, id)) {
removeFromSet(mVisibleDialogTrackedIds, id);
addToSet(mInvisibleDialogTrackedIds, id);
}
}
}
if (mVisibleTrackedIds == null) {
if (mIsTrackedSaveView && mVisibleTrackedIds.isEmpty()) {
if (sVerbose) {
Log.v(TAG, "No more visible ids. Invisible = " + mInvisibleTrackedIds);
}
finishSessionLocked(/* commitReason= */ COMMIT_REASON_VIEW_CHANGED);
}
if (mVisibleDialogTrackedIds.isEmpty()) {
if (sVerbose) {
Log.v(TAG, "No more visible ids. Invisible = " + mInvisibleDialogTrackedIds);
}
processNoVisibleTrackedAllViews();
}
}
@@ -3653,66 +3735,66 @@ public final class AutofillManager {
// The visibility of the views might have changed while the client was not be visible,
// hence update the visibility state for all views.
AutofillClient client = getClient();
ArraySet<AutofillId> updatedVisibleTrackedIds = null;
ArraySet<AutofillId> updatedInvisibleTrackedIds = null;
if (client != null) {
if (sVerbose) {
Log.v(TAG, "onVisibleForAutofillChangedLocked(): inv= " + mInvisibleTrackedIds
+ " vis=" + mVisibleTrackedIds);
}
if (mInvisibleTrackedIds != null) {
final ArrayList<AutofillId> orderedInvisibleIds =
new ArrayList<>(mInvisibleTrackedIds);
final boolean[] isVisible = client.autofillClientGetViewVisibility(
Helper.toArray(orderedInvisibleIds));
final int numInvisibleTrackedIds = orderedInvisibleIds.size();
for (int i = 0; i < numInvisibleTrackedIds; i++) {
final AutofillId id = orderedInvisibleIds.get(i);
if (isVisible[i]) {
updatedVisibleTrackedIds = addToSet(updatedVisibleTrackedIds, id);
if (sDebug) {
Log.d(TAG, "onVisibleForAutofill() " + id + " became visible");
}
} else {
updatedInvisibleTrackedIds = addToSet(updatedInvisibleTrackedIds, id);
}
}
}
if (mVisibleTrackedIds != null) {
final ArrayList<AutofillId> orderedVisibleIds =
new ArrayList<>(mVisibleTrackedIds);
final boolean[] isVisible = client.autofillClientGetViewVisibility(
Helper.toArray(orderedVisibleIds));
final int numVisibleTrackedIds = orderedVisibleIds.size();
for (int i = 0; i < numVisibleTrackedIds; i++) {
final AutofillId id = orderedVisibleIds.get(i);
if (isVisible[i]) {
updatedVisibleTrackedIds = addToSet(updatedVisibleTrackedIds, id);
} else {
updatedInvisibleTrackedIds = addToSet(updatedInvisibleTrackedIds, id);
if (sDebug) {
Log.d(TAG, "onVisibleForAutofill() " + id + " became invisible");
}
}
}
}
mInvisibleTrackedIds = updatedInvisibleTrackedIds;
mVisibleTrackedIds = updatedVisibleTrackedIds;
onVisibleForAutofillChangedInternalLocked(mVisibleTrackedIds, mInvisibleTrackedIds);
onVisibleForAutofillChangedInternalLocked(
mVisibleDialogTrackedIds, mInvisibleDialogTrackedIds);
}
if (mVisibleTrackedIds == null) {
if (mIsTrackedSaveView && mVisibleTrackedIds.isEmpty()) {
if (sVerbose) {
Log.v(TAG, "onVisibleForAutofillChangedLocked(): no more visible ids");
Log.v(TAG, "onVisibleForAutofillChangedLocked(): no more visible ids");
}
finishSessionLocked(/* commitReason= */ COMMIT_REASON_VIEW_CHANGED);
}
if (mVisibleDialogTrackedIds.isEmpty()) {
if (sVerbose) {
Log.v(TAG, "onVisibleForAutofillChangedLocked(): no more visible ids");
}
processNoVisibleTrackedAllViews();
}
}
void onVisibleForAutofillChangedInternalLocked(@NonNull ArraySet<AutofillId> visibleSet,
@NonNull ArraySet<AutofillId> invisibleSet) {
// The visibility of the views might have changed while the client was not be visible,
// hence update the visibility state for all views.
if (sVerbose) {
Log.v(TAG, "onVisibleForAutofillChangedLocked(): inv= " + invisibleSet
+ " vis=" + visibleSet);
}
ArraySet<AutofillId> allTrackedIds = new ArraySet<>();
allTrackedIds.addAll(visibleSet);
allTrackedIds.addAll(invisibleSet);
if (!allTrackedIds.isEmpty()) {
visibleSet.clear();
invisibleSet.clear();
initialTrackedViews(Helper.toArray(allTrackedIds), visibleSet, invisibleSet);
}
}
private void processNoVisibleTrackedAllViews() {
mShowAutofillDialogCalled = false;
}
void checkViewState(AutofillId id) {
if (mAllTrackedViews.contains(id)) {
return;
}
// Add the id as tracked to avoid triggering fill request again and again.
mAllTrackedViews.add(id);
if (mHasNewTrackedView) {
return;
}
// First one new tracks view
mIsFillRequested.set(false);
mHasNewTrackedView = true;
}
}

View File

@@ -24,6 +24,7 @@ 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;
import static android.service.autofill.FillRequest.FLAG_RESET_FILL_DIALOG_STATE;
import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
@@ -411,6 +412,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@GuardedBy("mLock")
private boolean mStartedLogEventWithoutFocus;
/**
* Keeps the fill dialog trigger ids of the last response. This invalidates
* the trigger ids of the previous response.
*/
@Nullable
@GuardedBy("mLock")
private AutofillId[] mLastFillDialogTriggerIds;
void onSwitchInputMethodLocked() {
// One caveat is that for the case where the focus is on a field for which regular autofill
// returns null, and augmented autofill is triggered, and then the user switches the input
@@ -1171,6 +1180,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
mLastFillDialogTriggerIds = response.getFillDialogTriggerIds();
final int flags = response.getFlags();
if ((flags & FillResponse.FLAG_DELAY_FILL) != 0) {
Slog.v(TAG, "Service requested to wait for delayed fill response.");
@@ -1277,6 +1288,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ (timedOut ? "timeout" : "failure"));
}
mService.resetLastResponse();
mLastFillDialogTriggerIds = null;
final LogMaker requestLog = mRequestLogs.get(requestId);
if (requestLog == null) {
Slog.w(TAG, "onFillRequestFailureOrTimeout(): no log for id " + requestId);
@@ -2973,6 +2985,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
if ((flags & FLAG_RESET_FILL_DIALOG_STATE) != 0) {
if (sDebug) Log.d(TAG, "force to reset fill dialog state");
mSessionFlags.mFillDialogDisabled = false;
}
switch(action) {
case ACTION_START_SESSION:
// View is triggering autofill.
@@ -3402,10 +3419,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
private boolean isFillDialogUiEnabled() {
// TODO read from Settings or somewhere
final boolean isSettingsEnabledFillDialog = true;
synchronized (mLock) {
return isSettingsEnabledFillDialog && !mSessionFlags.mFillDialogDisabled;
return !mSessionFlags.mFillDialogDisabled;
}
}
@@ -3431,14 +3446,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
AutofillId filledId, String filterText, int flags) {
if (!isFillDialogUiEnabled()) {
// Unsupported fill dialog UI
if (sDebug) Log.w(TAG, "requestShowFillDialog: fill dialog is disabled");
return false;
}
if ((flags & FillRequest.FLAG_IME_SHOWING) != 0) {
// IME is showing, fallback to normal suggestions UI
if (sDebug) Log.w(TAG, "requestShowFillDialog: IME is showing");
return false;
}
synchronized (mLock) {
if (mLastFillDialogTriggerIds == null
|| !ArrayUtils.contains(mLastFillDialogTriggerIds, filledId)) {
// Last fill dialog triggered ids are changed.
if (sDebug) Log.w(TAG, "Last fill dialog triggered ids are changed.");
return false;
}
}
final Drawable serviceIcon = getServiceIcon();
getUiForShowing().showFillDialog(filledId, response, filterText,
@@ -4278,6 +4304,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (mSessionFlags.mAugmentedAutofillOnly) {
pw.print(prefix); pw.println("For Augmented Autofill Only");
}
if (mSessionFlags.mFillDialogDisabled) {
pw.print(prefix); pw.println("Fill Dialog disabled");
}
if (mLastFillDialogTriggerIds != null) {
pw.print(prefix); pw.println("Last Fill Dialog trigger ids: ");
pw.println(mSelectedDatasetIds);
}
if (mAugmentedAutofillDestroyer != null) {
pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
}