diff options
| author | 2018-03-13 11:38:42 -0700 | |
|---|---|---|
| committer | 2018-03-13 14:58:38 -0700 | |
| commit | d9dbd27370afbaced7be9884b280dabaff352e30 (patch) | |
| tree | 390753e5fde91b1924dc924ca175f4d6422b09d2 | |
| parent | ee83dd2cd04387852997aa4c2cf66120612b9cb5 (diff) | |
autofill: ViewRootImpl.dispatchKeyFromIme() should not be dropped
ag/3628400 bypass unhandled keyevent from autofill to app window,
that solves the issue of using physical keyboard. But we still have
issue When user uses touch screen with IME.
There are two ways that IME interacts with app:
1. IME directly replaces text of TextView. (Sample app login screen)
2. IME calls ViewRootImpl.dispatchKeyFromIme. (Sample app credit card
screen)
In the second case, because we gave focus to autofill window,
ViewRootImpl will drop the event.
The fix checks if autofill window is showing fillui it should not
drop event. And dispatchKeyFromAutofill can use the same check, no
longer need FLAG_FROM_AUTOFILL.
Bug: 74527545
Test: Manually check with login and credit card example, using IME
touchscreen and "adb shell input keyevent". I am not able to write
cts test without a fake IME
Change-Id: I698423d83ee8f9151d03a39b49e85416f7d6b615
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 45 | ||||
| -rw-r--r-- | core/java/android/view/autofill/AutofillManager.java | 9 |
2 files changed, 38 insertions, 16 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index d908e7979cf7..d5216843f81e 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; import android.Manifest; import android.animation.LayoutTransition; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.ResourcesManager; @@ -4152,9 +4153,7 @@ public final class ViewRootImpl implements ViewParent, Log.v(TAG, "Dispatching key " + msg.obj + " from Autofill to " + mView); } KeyEvent event = (KeyEvent) msg.obj; - // send InputEvent to pre IME, set FLAG_FROM_AUTOFILL so the InputEvent - // wont be dropped as app window is not focus. - enqueueInputEvent(event, null, QueuedInputEvent.FLAG_FROM_AUTOFILL, true); + enqueueInputEvent(event, null, 0, true); } break; case MSG_CHECK_FOCUS: { InputMethodManager imm = InputMethodManager.peekInstance(); @@ -4447,7 +4446,7 @@ public final class ViewRootImpl implements ViewParent, return true; } else if ((!mAttachInfo.mHasWindowFocus && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER) - && (q.mFlags & QueuedInputEvent.FLAG_FROM_AUTOFILL) == 0) || mStopped + && !isAutofillUiShowing()) || mStopped || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON)) || (mPausedForTransition && !isBack(q.mEvent))) { // This is a focus event and the window doesn't currently have input focus or @@ -4782,18 +4781,11 @@ public final class ViewRootImpl implements ViewParent, ensureTouchMode(event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } - if (action == MotionEvent.ACTION_DOWN && mView instanceof ViewGroup) { + if (action == MotionEvent.ACTION_DOWN) { // Upon motion event within app window, close autofill ui. - ViewGroup decorView = (ViewGroup) mView; - if (decorView.getChildCount() > 0) { - // We cannot use decorView's Context for querying AutofillManager: DecorView's - // context is based on Application Context, it would allocate a different - // AutofillManager instance. - AutofillManager afm = (AutofillManager) decorView.getChildAt(0).getContext() - .getSystemService(Context.AUTOFILL_MANAGER_SERVICE); - if (afm != null) { - afm.requestHideFillUi(); - } + AutofillManager afm = getAutofillManager(); + if (afm != null) { + afm.requestHideFillUi(); } } @@ -6435,6 +6427,28 @@ public final class ViewRootImpl implements ViewParent, return mAudioManager; } + private @Nullable AutofillManager getAutofillManager() { + if (mView instanceof ViewGroup) { + ViewGroup decorView = (ViewGroup) mView; + if (decorView.getChildCount() > 0) { + // We cannot use decorView's Context for querying AutofillManager: DecorView's + // context is based on Application Context, it would allocate a different + // AutofillManager instance. + return decorView.getChildAt(0).getContext() + .getSystemService(AutofillManager.class); + } + } + return null; + } + + private boolean isAutofillUiShowing() { + AutofillManager afm = getAutofillManager(); + if (afm == null) { + return false; + } + return afm.isAutofillUiShowing(); + } + public AccessibilityInteractionController getAccessibilityInteractionController() { if (mView == null) { throw new IllegalStateException("getAccessibilityInteractionController" @@ -6840,7 +6854,6 @@ public final class ViewRootImpl implements ViewParent, public static final int FLAG_FINISHED_HANDLED = 1 << 3; public static final int FLAG_RESYNTHESIZED = 1 << 4; public static final int FLAG_UNHANDLED = 1 << 5; - public static final int FLAG_FROM_AUTOFILL = 1 << 6; public QueuedInputEvent mNext; diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 158c2ee0b2d0..c1092978cea0 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1407,6 +1407,15 @@ public final class AutofillManager { return client; } + /** + * Check if autofill ui is showing, must be called on UI thread. + * @hide + */ + public boolean isAutofillUiShowing() { + final AutofillClient client = mContext.getAutofillClient(); + return client != null & client.autofillClientIsFillUiShowing(); + } + /** @hide */ public void onAuthenticationResult(int authenticationId, Intent data, View focusView) { if (!hasAutofillFeature()) { |