Merge "Reset Autofill dialog if the content is changed" into tm-qpr-dev
This commit is contained in:
@@ -111,6 +111,12 @@ public final class FillRequest implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final @RequestFlags int FLAG_IME_SHOWING = 0x80;
|
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 */
|
/** @hide */
|
||||||
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
|
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_PASSWORD_INPUT_TYPE,
|
||||||
FLAG_VIEW_NOT_FOCUSED,
|
FLAG_VIEW_NOT_FOCUSED,
|
||||||
FLAG_SUPPORTS_FILL_DIALOG,
|
FLAG_SUPPORTS_FILL_DIALOG,
|
||||||
FLAG_IME_SHOWING
|
FLAG_IME_SHOWING,
|
||||||
|
FLAG_RESET_FILL_DIALOG_STATE
|
||||||
})
|
})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@DataClass.Generated.Member
|
@DataClass.Generated.Member
|
||||||
@@ -236,6 +243,8 @@ public final class FillRequest implements Parcelable {
|
|||||||
return "FLAG_SUPPORTS_FILL_DIALOG";
|
return "FLAG_SUPPORTS_FILL_DIALOG";
|
||||||
case FLAG_IME_SHOWING:
|
case FLAG_IME_SHOWING:
|
||||||
return "FLAG_IME_SHOWING";
|
return "FLAG_IME_SHOWING";
|
||||||
|
case FLAG_RESET_FILL_DIALOG_STATE:
|
||||||
|
return "FLAG_RESET_FILL_DIALOG_STATE";
|
||||||
default: return Integer.toHexString(value);
|
default: return Integer.toHexString(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,7 +321,8 @@ public final class FillRequest implements Parcelable {
|
|||||||
| FLAG_PASSWORD_INPUT_TYPE
|
| FLAG_PASSWORD_INPUT_TYPE
|
||||||
| FLAG_VIEW_NOT_FOCUSED
|
| FLAG_VIEW_NOT_FOCUSED
|
||||||
| FLAG_SUPPORTS_FILL_DIALOG
|
| FLAG_SUPPORTS_FILL_DIALOG
|
||||||
| FLAG_IME_SHOWING);
|
| FLAG_IME_SHOWING
|
||||||
|
| FLAG_RESET_FILL_DIALOG_STATE);
|
||||||
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
|
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
|
||||||
this.mDelayedFillIntentSender = delayedFillIntentSender;
|
this.mDelayedFillIntentSender = delayedFillIntentSender;
|
||||||
|
|
||||||
@@ -473,7 +483,8 @@ public final class FillRequest implements Parcelable {
|
|||||||
| FLAG_PASSWORD_INPUT_TYPE
|
| FLAG_PASSWORD_INPUT_TYPE
|
||||||
| FLAG_VIEW_NOT_FOCUSED
|
| FLAG_VIEW_NOT_FOCUSED
|
||||||
| FLAG_SUPPORTS_FILL_DIALOG
|
| FLAG_SUPPORTS_FILL_DIALOG
|
||||||
| FLAG_IME_SHOWING);
|
| FLAG_IME_SHOWING
|
||||||
|
| FLAG_RESET_FILL_DIALOG_STATE);
|
||||||
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
|
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
|
||||||
this.mDelayedFillIntentSender = delayedFillIntentSender;
|
this.mDelayedFillIntentSender = delayedFillIntentSender;
|
||||||
|
|
||||||
@@ -495,10 +506,10 @@ public final class FillRequest implements Parcelable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@DataClass.Generated(
|
@DataClass.Generated(
|
||||||
time = 1647856966565L,
|
time = 1663290803064L,
|
||||||
codegenVersion = "1.0.23",
|
codegenVersion = "1.0.23",
|
||||||
sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
|
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
|
@Deprecated
|
||||||
private void __metadata() {}
|
private void __metadata() {}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package android.view.autofill;
|
|||||||
import static android.service.autofill.FillRequest.FLAG_IME_SHOWING;
|
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_MANUAL_REQUEST;
|
||||||
import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
|
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_SUPPORTS_FILL_DIALOG;
|
||||||
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
|
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
|
||||||
import static android.view.ContentInfo.SOURCE_AUTOFILL;
|
import static android.view.ContentInfo.SOURCE_AUTOFILL;
|
||||||
@@ -715,7 +716,7 @@ public final class AutofillManager {
|
|||||||
* Autofill will automatically trigger a fill request after activity
|
* Autofill will automatically trigger a fill request after activity
|
||||||
* start if there is any field is autofillable. But if there is a field that
|
* start if there is any field is autofillable. But if there is a field that
|
||||||
* triggered autofill, it is unnecessary to trigger again through
|
* triggered autofill, it is unnecessary to trigger again through
|
||||||
* AutofillManager#notifyViewEnteredForActivityStarted.
|
* AutofillManager#notifyViewEnteredForFillDialog.
|
||||||
*/
|
*/
|
||||||
private AtomicBoolean mIsFillRequested;
|
private AtomicBoolean mIsFillRequested;
|
||||||
|
|
||||||
@@ -728,6 +729,10 @@ public final class AutofillManager {
|
|||||||
|
|
||||||
private final String[] mFillDialogEnabledHints;
|
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 */
|
/** @hide */
|
||||||
public interface AutofillClient {
|
public interface AutofillClient {
|
||||||
/**
|
/**
|
||||||
@@ -1173,6 +1178,16 @@ public final class AutofillManager {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public void notifyViewEnteredForFillDialog(View v) {
|
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.
|
// Skip if the fill request has been performed for a view.
|
||||||
if (mIsFillRequested.get()) {
|
if (mIsFillRequested.get()) {
|
||||||
return;
|
return;
|
||||||
@@ -1299,6 +1314,10 @@ public final class AutofillManager {
|
|||||||
}
|
}
|
||||||
mForAugmentedAutofillOnly = false;
|
mForAugmentedAutofillOnly = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((flags & FLAG_SUPPORTS_FILL_DIALOG) != 0) {
|
||||||
|
flags |= FLAG_RESET_FILL_DIALOG_STATE;
|
||||||
|
}
|
||||||
updateSessionLocked(id, null, value, ACTION_VIEW_ENTERED, flags);
|
updateSessionLocked(id, null, value, ACTION_VIEW_ENTERED, flags);
|
||||||
}
|
}
|
||||||
addEnteredIdLocked(id);
|
addEnteredIdLocked(id);
|
||||||
@@ -2165,6 +2184,7 @@ public final class AutofillManager {
|
|||||||
mIsFillRequested.set(false);
|
mIsFillRequested.set(false);
|
||||||
mShowAutofillDialogCalled = false;
|
mShowAutofillDialogCalled = false;
|
||||||
mFillDialogTriggerIds = null;
|
mFillDialogTriggerIds = null;
|
||||||
|
mAllTrackedViews.clear();
|
||||||
if (resetEnteredIds) {
|
if (resetEnteredIds) {
|
||||||
mEnteredIds = null;
|
mEnteredIds = null;
|
||||||
}
|
}
|
||||||
@@ -2702,14 +2722,9 @@ public final class AutofillManager {
|
|||||||
+ ", mFillableIds=" + mFillableIds
|
+ ", mFillableIds=" + mFillableIds
|
||||||
+ ", mEnabled=" + mEnabled
|
+ ", mEnabled=" + mEnabled
|
||||||
+ ", mSessionId=" + mSessionId);
|
+ ", mSessionId=" + mSessionId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
if (mEnabled && mSessionId == sessionId) {
|
if (mEnabled && mSessionId == sessionId) {
|
||||||
if (saveOnAllViewsInvisible) {
|
|
||||||
mTrackedViews = new TrackedViews(trackedIds);
|
|
||||||
} else {
|
|
||||||
mTrackedViews = null;
|
|
||||||
}
|
|
||||||
mSaveOnFinish = saveOnFinish;
|
mSaveOnFinish = saveOnFinish;
|
||||||
if (fillableIds != null) {
|
if (fillableIds != null) {
|
||||||
if (mFillableIds == null) {
|
if (mFillableIds == null) {
|
||||||
@@ -2731,6 +2746,27 @@ public final class AutofillManager {
|
|||||||
mSaveTriggerId = saveTriggerId;
|
mSaveTriggerId = saveTriggerId;
|
||||||
setNotifyOnClickLocked(mSaveTriggerId, true);
|
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 {
|
private class TrackedViews {
|
||||||
/** Visible tracked views */
|
/** Visible tracked views */
|
||||||
@Nullable private ArraySet<AutofillId> mVisibleTrackedIds;
|
@NonNull private final ArraySet<AutofillId> mVisibleTrackedIds;
|
||||||
|
|
||||||
/** Invisible tracked views */
|
/** 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.
|
* Check if set is null or value is in set.
|
||||||
@@ -3571,11 +3616,44 @@ public final class AutofillManager {
|
|||||||
*
|
*
|
||||||
* @param trackedIds The views to be tracked
|
* @param trackedIds The views to be tracked
|
||||||
*/
|
*/
|
||||||
TrackedViews(@Nullable AutofillId[] trackedIds) {
|
TrackedViews(@Nullable AutofillId[] trackedIds, @Nullable AutofillId[] allTrackedIds) {
|
||||||
final AutofillClient client = getClient();
|
mVisibleTrackedIds = new ArraySet<>();
|
||||||
if (!ArrayUtils.isEmpty(trackedIds) && client != null) {
|
mInvisibleTrackedIds = new ArraySet<>();
|
||||||
final boolean[] isVisible;
|
if (!ArrayUtils.isEmpty(trackedIds)) {
|
||||||
|
mIsTrackedSaveView = true;
|
||||||
|
initialTrackedViews(trackedIds, mVisibleTrackedIds, mInvisibleTrackedIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
+ " allTrackedIds=" + Arrays.toString(allTrackedIds)
|
||||||
|
+ " mVisibleDialogTrackedIds=" + mVisibleDialogTrackedIds
|
||||||
|
+ " mInvisibleDialogTrackedIds=" + mInvisibleDialogTrackedIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (client.autofillClientIsVisibleForAutofill()) {
|
||||||
if (sVerbose) Log.v(TAG, "client is visible, check tracked ids");
|
if (sVerbose) Log.v(TAG, "client is visible, check tracked ids");
|
||||||
isVisible = client.autofillClientGetViewVisibility(trackedIds);
|
isVisible = client.autofillClientGetViewVisibility(trackedIds);
|
||||||
@@ -3590,24 +3668,13 @@ public final class AutofillManager {
|
|||||||
id.resetSessionId();
|
id.resetSessionId();
|
||||||
|
|
||||||
if (isVisible[i]) {
|
if (isVisible[i]) {
|
||||||
mVisibleTrackedIds = addToSet(mVisibleTrackedIds, id);
|
addToSet(visibleSet, id);
|
||||||
} else {
|
} else {
|
||||||
mInvisibleTrackedIds = addToSet(mInvisibleTrackedIds, id);
|
addToSet(invisibleSet, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sVerbose) {
|
|
||||||
Log.v(TAG, "TrackedViews(trackedIds=" + Arrays.toString(trackedIds) + "): "
|
|
||||||
+ " mVisibleTrackedIds=" + mVisibleTrackedIds
|
|
||||||
+ " mInvisibleTrackedIds=" + mInvisibleTrackedIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mVisibleTrackedIds == null) {
|
|
||||||
finishSessionLocked(/* commitReason= */ COMMIT_REASON_VIEW_CHANGED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a {@link View view's} visibility changes.
|
* Called when a {@link View view's} visibility changes.
|
||||||
*
|
*
|
||||||
@@ -3624,22 +3691,37 @@ public final class AutofillManager {
|
|||||||
if (isClientVisibleForAutofillLocked()) {
|
if (isClientVisibleForAutofillLocked()) {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
if (isInSet(mInvisibleTrackedIds, id)) {
|
if (isInSet(mInvisibleTrackedIds, id)) {
|
||||||
mInvisibleTrackedIds = removeFromSet(mInvisibleTrackedIds, id);
|
removeFromSet(mInvisibleTrackedIds, id);
|
||||||
mVisibleTrackedIds = addToSet(mVisibleTrackedIds, id);
|
addToSet(mVisibleTrackedIds, id);
|
||||||
|
}
|
||||||
|
if (isInSet(mInvisibleDialogTrackedIds, id)) {
|
||||||
|
removeFromSet(mInvisibleDialogTrackedIds, id);
|
||||||
|
addToSet(mVisibleDialogTrackedIds, id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isInSet(mVisibleTrackedIds, id)) {
|
if (isInSet(mVisibleTrackedIds, id)) {
|
||||||
mVisibleTrackedIds = removeFromSet(mVisibleTrackedIds, id);
|
removeFromSet(mVisibleTrackedIds, id);
|
||||||
mInvisibleTrackedIds = addToSet(mInvisibleTrackedIds, id);
|
addToSet(mInvisibleTrackedIds, id);
|
||||||
|
}
|
||||||
|
if (isInSet(mVisibleDialogTrackedIds, id)) {
|
||||||
|
removeFromSet(mVisibleDialogTrackedIds, id);
|
||||||
|
addToSet(mInvisibleDialogTrackedIds, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mVisibleTrackedIds == null) {
|
if (mIsTrackedSaveView && mVisibleTrackedIds.isEmpty()) {
|
||||||
if (sVerbose) {
|
if (sVerbose) {
|
||||||
Log.v(TAG, "No more visible ids. Invisible = " + mInvisibleTrackedIds);
|
Log.v(TAG, "No more visible ids. Invisible = " + mInvisibleTrackedIds);
|
||||||
}
|
}
|
||||||
finishSessionLocked(/* commitReason= */ COMMIT_REASON_VIEW_CHANGED);
|
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,
|
// The visibility of the views might have changed while the client was not be visible,
|
||||||
// hence update the visibility state for all views.
|
// hence update the visibility state for all views.
|
||||||
AutofillClient client = getClient();
|
AutofillClient client = getClient();
|
||||||
ArraySet<AutofillId> updatedVisibleTrackedIds = null;
|
|
||||||
ArraySet<AutofillId> updatedInvisibleTrackedIds = null;
|
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
if (sVerbose) {
|
if (sVerbose) {
|
||||||
Log.v(TAG, "onVisibleForAutofillChangedLocked(): inv= " + mInvisibleTrackedIds
|
Log.v(TAG, "onVisibleForAutofillChangedLocked(): inv= " + mInvisibleTrackedIds
|
||||||
+ " vis=" + mVisibleTrackedIds);
|
+ " 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();
|
onVisibleForAutofillChangedInternalLocked(mVisibleTrackedIds, mInvisibleTrackedIds);
|
||||||
for (int i = 0; i < numInvisibleTrackedIds; i++) {
|
onVisibleForAutofillChangedInternalLocked(
|
||||||
final AutofillId id = orderedInvisibleIds.get(i);
|
mVisibleDialogTrackedIds, mInvisibleDialogTrackedIds);
|
||||||
if (isVisible[i]) {
|
|
||||||
updatedVisibleTrackedIds = addToSet(updatedVisibleTrackedIds, id);
|
|
||||||
|
|
||||||
if (sDebug) {
|
|
||||||
Log.d(TAG, "onVisibleForAutofill() " + id + " became visible");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updatedInvisibleTrackedIds = addToSet(updatedInvisibleTrackedIds, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mVisibleTrackedIds != null) {
|
if (mIsTrackedSaveView && mVisibleTrackedIds.isEmpty()) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mVisibleTrackedIds == null) {
|
|
||||||
if (sVerbose) {
|
if (sVerbose) {
|
||||||
Log.v(TAG, "onVisibleForAutofillChangedLocked(): no more visible ids");
|
Log.v(TAG, "onVisibleForAutofillChangedLocked(): no more visible ids");
|
||||||
}
|
}
|
||||||
finishSessionLocked(/* commitReason= */ COMMIT_REASON_VIEW_CHANGED);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.FillEventHistory.Event.UI_TYPE_UNKNOWN;
|
||||||
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
|
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_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_SUPPORTS_FILL_DIALOG;
|
||||||
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
|
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
|
||||||
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
|
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
|
||||||
@@ -411,6 +412,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private boolean mStartedLogEventWithoutFocus;
|
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() {
|
void onSwitchInputMethodLocked() {
|
||||||
// One caveat is that for the case where the focus is on a field for which regular autofill
|
// 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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLastFillDialogTriggerIds = response.getFillDialogTriggerIds();
|
||||||
|
|
||||||
final int flags = response.getFlags();
|
final int flags = response.getFlags();
|
||||||
if ((flags & FillResponse.FLAG_DELAY_FILL) != 0) {
|
if ((flags & FillResponse.FLAG_DELAY_FILL) != 0) {
|
||||||
Slog.v(TAG, "Service requested to wait for delayed fill response.");
|
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"));
|
+ (timedOut ? "timeout" : "failure"));
|
||||||
}
|
}
|
||||||
mService.resetLastResponse();
|
mService.resetLastResponse();
|
||||||
|
mLastFillDialogTriggerIds = null;
|
||||||
final LogMaker requestLog = mRequestLogs.get(requestId);
|
final LogMaker requestLog = mRequestLogs.get(requestId);
|
||||||
if (requestLog == null) {
|
if (requestLog == null) {
|
||||||
Slog.w(TAG, "onFillRequestFailureOrTimeout(): no log for id " + requestId);
|
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) {
|
switch(action) {
|
||||||
case ACTION_START_SESSION:
|
case ACTION_START_SESSION:
|
||||||
// View is triggering autofill.
|
// View is triggering autofill.
|
||||||
@@ -3402,10 +3419,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFillDialogUiEnabled() {
|
private boolean isFillDialogUiEnabled() {
|
||||||
// TODO read from Settings or somewhere
|
|
||||||
final boolean isSettingsEnabledFillDialog = true;
|
|
||||||
synchronized (mLock) {
|
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) {
|
AutofillId filledId, String filterText, int flags) {
|
||||||
if (!isFillDialogUiEnabled()) {
|
if (!isFillDialogUiEnabled()) {
|
||||||
// Unsupported fill dialog UI
|
// Unsupported fill dialog UI
|
||||||
|
if (sDebug) Log.w(TAG, "requestShowFillDialog: fill dialog is disabled");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & FillRequest.FLAG_IME_SHOWING) != 0) {
|
if ((flags & FillRequest.FLAG_IME_SHOWING) != 0) {
|
||||||
// IME is showing, fallback to normal suggestions UI
|
// IME is showing, fallback to normal suggestions UI
|
||||||
|
if (sDebug) Log.w(TAG, "requestShowFillDialog: IME is showing");
|
||||||
return false;
|
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();
|
final Drawable serviceIcon = getServiceIcon();
|
||||||
|
|
||||||
getUiForShowing().showFillDialog(filledId, response, filterText,
|
getUiForShowing().showFillDialog(filledId, response, filterText,
|
||||||
@@ -4278,6 +4304,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
|
|||||||
if (mSessionFlags.mAugmentedAutofillOnly) {
|
if (mSessionFlags.mAugmentedAutofillOnly) {
|
||||||
pw.print(prefix); pw.println("For Augmented Autofill Only");
|
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) {
|
if (mAugmentedAutofillDestroyer != null) {
|
||||||
pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
|
pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user