From 6ecbf08772d73cea6b78b5d8eae4e925e0599385 Mon Sep 17 00:00:00 2001 From: Ming-Shin Lu Date: Mon, 1 Jun 2020 17:42:32 +0800 Subject: [PATCH] Report WINDOW_FOCUS_GAIN_REPORT_ONLY when the served connection remains When we tried CL[1] to fix Gboard Translation UI dialog dismissed that keeping the served view when focused to the next window, although we can skip starting new input when the window focused back as the behavior of Q, However, we overlooked in R, IME insets will rely on IMS#reportStartInput to get the updated IME input target, which will out of sync for the above case. To fix this regression, we report the next window focus gain to IMMS with WINDOW_FOCUS_GAIN_REPORT_ONLY when the next focused view is same as current served view and the served input connection remains. so that in IMMS side won't get StartInputFlags.INITIAL_CONNECTION flags to set restarting as false when calling IInputMethod#startInput to IMS, and in IMS side will still call reportStartInput to WMS for updating IME input target without additional onFinishInputView callback to client. [1]: I8d4fff94ba9313b773bc27fcbd019cc88580d3e9 Fix: 152373385 Bug: 155781821 Test: atest CtsInputMethodTestCases Test: manual, make sure Bug 155781821 comment #10 works: 1) Launch video call in Hangouts. 2) End call. 3) Click on the text box. 4) Expect Soft-Keyboard shown Test: make sure not break Bug 148489857 and Bug 148788569, following auto / manual test to verify: - Auto: atest FocusHandlingTest#testKeyboardStateAfterImeFocusableFlagChanged - Manual: 1) Build / install EditTextVariations 2) Select menu -> Direct-Reply, make sure Notification comes up. 3) Tap EditText on Notification, verify soft-keyboard is visible. Change-Id: I45a9814d812ad906f417c24200fd4219959e2423 --- .../java/android/view/ImeFocusController.java | 8 ++++++ .../view/inputmethod/InputMethodManager.java | 26 ++++++++++++++++--- .../inputmethod/StartInputReason.java | 5 ++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java index a4800726bbe8b..825077ffd57a5 100644 --- a/core/java/android/view/ImeFocusController.java +++ b/core/java/android/view/ImeFocusController.java @@ -125,6 +125,13 @@ public final class ImeFocusController { final View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView; onViewFocusChanged(viewForWindowFocus, true); + // Skip starting input when the next focused view is same as served view and the served + // input connection still exists. + final boolean nextFocusIsServedView = mServedView != null && mServedView == focusedView; + if (nextFocusIsServedView && immDelegate.isAcceptingText()) { + forceFocus = false; + } + immDelegate.startInputAsyncOnWindowFocusGain(viewForWindowFocus, windowAttribute.softInputMode, windowAttribute.flags, forceFocus); } @@ -247,6 +254,7 @@ public final class ImeFocusController { void setCurrentRootView(ViewRootImpl rootView); boolean isCurrentRootView(ViewRootImpl rootView); boolean isRestartOnNextWindowFocus(boolean reset); + boolean isAcceptingText(); } public View getServedView() { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 71dd6653f6a65..477dd1d132953 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -616,12 +616,19 @@ public final class InputMethodManager { // For some reason we didn't do a startInput + windowFocusGain, so // we'll just do a window focus gain and call it a day. try { - if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput"); + View servedView = controller.getServedView(); + boolean nextFocusIsServedView = servedView != null && servedView == focusedView; + if (DEBUG) { + Log.v(TAG, "Reporting focus gain, without startInput" + + ", nextFocusIsServedView=" + nextFocusIsServedView); + } mService.startInputOrWindowGainedFocus( StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient, focusedView.getWindowToken(), startInputFlags, softInputMode, windowFlags, - null, null, 0 /* missingMethodFlags */, + nextFocusIsServedView ? mCurrentTextBoxAttribute : null, + nextFocusIsServedView ? mServedInputConnectionWrapper : null, + 0 /* missingMethodFlags */, mCurRootView.mContext.getApplicationInfo().targetSdkVersion); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -646,8 +653,7 @@ public final class InputMethodManager { public void setCurrentRootView(ViewRootImpl rootView) { synchronized (mH) { if (mCurRootView != null) { - // Reset the last served view and restart window focus state of the root view. - mCurRootView.getImeFocusController().setServedView(null); + // Restart the input when the next window focus state of the root view changed. mRestartOnNextWindowFocus = true; } mCurRootView = rootView; @@ -677,6 +683,18 @@ public final class InputMethodManager { } return result; } + + /** + * For {@link ImeFocusController} to check if the currently served view is accepting full + * text edits. + */ + @Override + public boolean isAcceptingText() { + synchronized (mH) { + return mServedInputConnectionWrapper != null + && mServedInputConnectionWrapper.getInputConnection() != null; + } + } } /** @hide */ diff --git a/core/java/com/android/internal/inputmethod/StartInputReason.java b/core/java/com/android/internal/inputmethod/StartInputReason.java index a01c45919b8fc..a4eaa21538f73 100644 --- a/core/java/com/android/internal/inputmethod/StartInputReason.java +++ b/core/java/com/android/internal/inputmethod/StartInputReason.java @@ -50,8 +50,9 @@ public @interface StartInputReason { int WINDOW_FOCUS_GAIN = 1; /** * {@link android.view.Window} gained focus but there is no {@link android.view.View} that is - * eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports - * this window focus change event. + * eligible to have IME focus, or the focused view is same as current served view and its + * input connection remains. {@link android.view.inputmethod.InputMethodManager} just reports + * this window focus change event to sync IME input target for system. */ int WINDOW_FOCUS_GAIN_REPORT_ONLY = 2; /**