Merge "Fix Autofill dialog does not work" into tm-dev

This commit is contained in:
Ahaan Ugale
2022-05-05 16:27:54 +00:00
committed by Android (Google) Code Review
3 changed files with 31 additions and 65 deletions

View File

@@ -8206,24 +8206,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (canNotifyAutofillEnterExitEvent()) { if (canNotifyAutofillEnterExitEvent()) {
AutofillManager afm = getAutofillManager(); AutofillManager afm = getAutofillManager();
if (afm != null) { if (afm != null) {
if (enter && isFocused()) { if (enter) {
// We have not been laid out yet, hence cannot evaluate // We have not been laid out yet, hence cannot evaluate
// whether this view is visible to the user, we will do // whether this view is visible to the user, we will do
// the evaluation once layout is complete. // the evaluation once layout is complete.
if (!isLaidOut()) { if (!isLaidOut()) {
mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT; mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
} else if (isVisibleToUser()) { } else if (isVisibleToUser()) {
// TODO This is a potential problem that View gets focus before it's visible if (isFocused()) {
// to User. Ideally View should handle the event when isVisibleToUser() // TODO This is a potential problem that View gets focus before it's
// becomes true where it should issue notifyViewEntered(). // visible to User. Ideally View should handle the event when
afm.notifyViewEntered(this); // isVisibleToUser() becomes true where it should issue
} else { // notifyViewEntered().
afm.enableFillRequestActivityStarted(this); afm.notifyViewEntered(this);
} else {
afm.notifyViewEnteredForFillDialog(this);
}
} }
} else if (!enter && !isFocused()) { } else if (!isFocused()) {
afm.notifyViewExited(this); afm.notifyViewExited(this);
} else if (enter) {
afm.enableFillRequestActivityStarted(this);
} }
} }
} }

View File

@@ -590,7 +590,6 @@ public final class ViewRootImpl implements ViewParent,
@Nullable @Nullable
int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED; int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED;
boolean mPerformContentCapture; boolean mPerformContentCapture;
boolean mPerformAutoFill;
boolean mReportNextDraw; boolean mReportNextDraw;
@@ -912,7 +911,6 @@ public final class ViewRootImpl implements ViewParent,
mPreviousTransparentRegion = new Region(); mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added mFirst = true; // true for the first time the view is added
mPerformContentCapture = true; // also true for the first time the view is added mPerformContentCapture = true; // also true for the first time the view is added
mPerformAutoFill = true;
mAdded = false; mAdded = false;
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
context); context);
@@ -4331,18 +4329,6 @@ public final class ViewRootImpl implements ViewParent,
if (mPerformContentCapture) { if (mPerformContentCapture) {
performContentCaptureInitialReport(); performContentCaptureInitialReport();
} }
if (mPerformAutoFill) {
notifyEnterForAutoFillIfNeeded();
}
}
private void notifyEnterForAutoFillIfNeeded() {
mPerformAutoFill = false;
final AutofillManager afm = getAutofillManager();
if (afm != null) {
afm.notifyViewEnteredForActivityStarted(mView);
}
} }
/** /**

View File

@@ -102,6 +102,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import sun.misc.Cleaner; import sun.misc.Cleaner;
@@ -644,16 +645,6 @@ public final class AutofillManager {
@GuardedBy("mLock") @GuardedBy("mLock")
private boolean mEnabledForAugmentedAutofillOnly; private boolean mEnabledForAugmentedAutofillOnly;
/**
* Indicates whether there are any fields that need to do a fill request
* after the activity starts.
*
* Note: This field will be set to true multiple times if there are many
* autofillable views. So needs to check mIsFillRequested at the same time to
* avoid re-trigger autofill.
*/
private boolean mRequireAutofill;
/** /**
* Indicates whether there is already a field to do a fill request after * Indicates whether there is already a field to do a fill request after
* the activity started. * the activity started.
@@ -663,7 +654,7 @@ public final class AutofillManager {
* triggered autofill, it is unnecessary to trigger again through * triggered autofill, it is unnecessary to trigger again through
* AutofillManager#notifyViewEnteredForActivityStarted. * AutofillManager#notifyViewEnteredForActivityStarted.
*/ */
private boolean mIsFillRequested; private AtomicBoolean mIsFillRequested;
@Nullable private List<AutofillId> mFillDialogTriggerIds; @Nullable private List<AutofillId> mFillDialogTriggerIds;
@@ -811,8 +802,7 @@ public final class AutofillManager {
mContext = Objects.requireNonNull(context, "context cannot be null"); mContext = Objects.requireNonNull(context, "context cannot be null");
mService = service; mService = service;
mOptions = context.getAutofillOptions(); mOptions = context.getAutofillOptions();
mIsFillRequested = false; mIsFillRequested = new AtomicBoolean(false);
mRequireAutofill = false;
mIsFillDialogEnabled = DeviceConfig.getBoolean( mIsFillDialogEnabled = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_AUTOFILL, DeviceConfig.NAMESPACE_AUTOFILL,
@@ -1113,22 +1103,31 @@ public final class AutofillManager {
} }
/** /**
* The view have the allowed autofill hints, marked to perform a fill request after layout if * The {@link #DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or the view have
* the field does not trigger a fill request. * the allowed autofill hints, performs a fill request to know there is any field supported
* fill dialog.
* *
* @hide * @hide
*/ */
public void enableFillRequestActivityStarted(View v) { public void notifyViewEnteredForFillDialog(View v) {
if (mRequireAutofill) { // Skip if the fill request has been performed for a view.
if (mIsFillRequested.get()) {
return; return;
} }
if (mIsFillDialogEnabled if (mIsFillDialogEnabled
|| ArrayUtils.containsAny(v.getAutofillHints(), mFillDialogEnabledHints)) { || ArrayUtils.containsAny(v.getAutofillHints(), mFillDialogEnabledHints)) {
if (sDebug) { if (sDebug) {
Log.d(TAG, "Trigger fill request at starting"); Log.d(TAG, "Trigger fill request at view entered");
} }
mRequireAutofill = true;
// Note: No need for atomic getAndSet as this method is called on the UI thread.
mIsFillRequested.set(true);
int flags = FLAG_SUPPORTS_FILL_DIALOG;
flags |= FLAG_VIEW_NOT_FOCUSED;
// use root view, so autofill UI does not trigger immediately.
notifyViewEntered(v.getRootView(), flags);
} }
} }
@@ -1136,25 +1135,6 @@ public final class AutofillManager {
return mIsFillDialogEnabled || !ArrayUtils.isEmpty(mFillDialogEnabledHints); return mIsFillDialogEnabled || !ArrayUtils.isEmpty(mFillDialogEnabledHints);
} }
/**
* Notify autofill to do a fill request while the activity started.
*
* @hide
*/
public void notifyViewEnteredForActivityStarted(@NonNull View view) {
if (!hasAutofillFeature() || !hasFillDialogUiFeature()) {
return;
}
if (!mRequireAutofill || mIsFillRequested) {
return;
}
int flags = FLAG_SUPPORTS_FILL_DIALOG;
flags |= FLAG_VIEW_NOT_FOCUSED;
notifyViewEntered(view, flags);
}
private int getImeStateFlag(View v) { private int getImeStateFlag(View v) {
final WindowInsets rootWindowInsets = v.getRootWindowInsets(); final WindowInsets rootWindowInsets = v.getRootWindowInsets();
if (rootWindowInsets != null && rootWindowInsets.isVisible(WindowInsets.Type.ime())) { if (rootWindowInsets != null && rootWindowInsets.isVisible(WindowInsets.Type.ime())) {
@@ -1203,7 +1183,7 @@ public final class AutofillManager {
} }
AutofillCallback callback; AutofillCallback callback;
synchronized (mLock) { synchronized (mLock) {
mIsFillRequested = true; mIsFillRequested.set(true);
callback = notifyViewEnteredLocked(view, flags); callback = notifyViewEnteredLocked(view, flags);
} }
@@ -2119,8 +2099,7 @@ public final class AutofillManager {
mFillableIds = null; mFillableIds = null;
mSaveTriggerId = null; mSaveTriggerId = null;
mIdShownFillUi = null; mIdShownFillUi = null;
mIsFillRequested = false; mIsFillRequested.set(false);
mRequireAutofill = false;
mShowAutofillDialogCalled = false; mShowAutofillDialogCalled = false;
mFillDialogTriggerIds = null; mFillDialogTriggerIds = null;
if (resetEnteredIds) { if (resetEnteredIds) {