RESTRICT AUTOMERGE Reland "Fix showing keyboard without editor focused.."
Resolve SearchViewTest and InputMethodServiceTest failure when landing CL[1] in QPR branch. Also, CL[1] mentioned window focus behavior changes from R, ignoring STATE_VISIBLE or STATE_ALWAYS_VISIBLE request doesn't enough to fix unexpected keyboard visible issue when same window focused with the above softInput flag without editor focus, since there is no additional unspecified window focus to hide the current soft-input as prior to R's behavior. To fix that, we introduced new SoftInputShowHideReason to hide soft-input when the same window focused without valid editor focus after screen unlock, in order to align with the behavior prior to R. [1]: I37ae6e30d1de581ba15131c2a90396b3a522a4d6 Bug: 161506356 Test: atest CtsInputMethodTestCases Change-Id: Id51863a5b67d5d79d903adf43f19b52bd139e03f
This commit is contained in:
@@ -611,7 +611,8 @@ public final class InputMethodManager {
|
|||||||
@Override
|
@Override
|
||||||
public void startInputAsyncOnWindowFocusGain(View focusedView,
|
public void startInputAsyncOnWindowFocusGain(View focusedView,
|
||||||
@SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) {
|
@SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) {
|
||||||
final int startInputFlags = getStartInputFlags(focusedView, 0);
|
int startInputFlags = getStartInputFlags(focusedView, 0);
|
||||||
|
startInputFlags |= StartInputFlags.WINDOW_GAINED_FOCUS;
|
||||||
|
|
||||||
final ImeFocusController controller = getFocusController();
|
final ImeFocusController controller = getFocusController();
|
||||||
if (controller == null) {
|
if (controller == null) {
|
||||||
|
|||||||
@@ -224,6 +224,8 @@ public final class InputMethodDebug {
|
|||||||
return "HIDE_DOCKED_STACK_ATTACHED";
|
return "HIDE_DOCKED_STACK_ATTACHED";
|
||||||
case SoftInputShowHideReason.HIDE_RECENTS_ANIMATION:
|
case SoftInputShowHideReason.HIDE_RECENTS_ANIMATION:
|
||||||
return "HIDE_RECENTS_ANIMATION";
|
return "HIDE_RECENTS_ANIMATION";
|
||||||
|
case SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR:
|
||||||
|
return "HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR";
|
||||||
default:
|
default:
|
||||||
return "Unknown=" + reason;
|
return "Unknown=" + reason;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ import java.lang.annotation.Retention;
|
|||||||
SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME,
|
SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME,
|
||||||
SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED,
|
SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED,
|
||||||
SoftInputShowHideReason.HIDE_RECENTS_ANIMATION,
|
SoftInputShowHideReason.HIDE_RECENTS_ANIMATION,
|
||||||
SoftInputShowHideReason.HIDE_BUBBLES})
|
SoftInputShowHideReason.HIDE_BUBBLES,
|
||||||
|
SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR})
|
||||||
public @interface SoftInputShowHideReason {
|
public @interface SoftInputShowHideReason {
|
||||||
/** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
|
/** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
|
||||||
int SHOW_SOFT_INPUT = 0;
|
int SHOW_SOFT_INPUT = 0;
|
||||||
@@ -147,4 +148,17 @@ public @interface SoftInputShowHideReason {
|
|||||||
* switching, or collapsing Bubbles.
|
* switching, or collapsing Bubbles.
|
||||||
*/
|
*/
|
||||||
int HIDE_BUBBLES = 19;
|
int HIDE_BUBBLES = 19;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide soft input when focusing the same window (e.g. screen turned-off and turn-on) which no
|
||||||
|
* valid focused editor.
|
||||||
|
*
|
||||||
|
* Note: From Android R, the window focus change callback is processed by InputDispatcher,
|
||||||
|
* some focus behavior changes (e.g. There are an activity with a dialog window, after
|
||||||
|
* screen turned-off and turned-on, before Android R the window focus sequence would be
|
||||||
|
* the activity first and then the dialog focused, however, in R the focus sequence would be
|
||||||
|
* only the dialog focused as it's the latest window with input focus) makes we need to hide
|
||||||
|
* soft-input when the same window focused again to align with the same behavior prior to R.
|
||||||
|
*/
|
||||||
|
int HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR = 20;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,4 +47,10 @@ public @interface StartInputFlags {
|
|||||||
* documented hence we probably need to revisit this though.
|
* documented hence we probably need to revisit this though.
|
||||||
*/
|
*/
|
||||||
int INITIAL_CONNECTION = 4;
|
int INITIAL_CONNECTION = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start input happens when the window gained focus to call
|
||||||
|
* {@code android.view.inputmethod.InputMethodManager#startInputAsyncOnWindowFocusGain}.
|
||||||
|
*/
|
||||||
|
int WINDOW_GAINED_FOCUS = 8;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3275,6 +3275,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
|
boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
|
||||||
@SoftInputShowHideReason int reason) {
|
@SoftInputShowHideReason int reason) {
|
||||||
|
if (mCurClient == null || mCurClient.curSession == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
|
if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
|
||||||
&& (mShowExplicitlyRequested || mShowForced)) {
|
&& (mShowExplicitlyRequested || mShowForced)) {
|
||||||
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
|
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
|
||||||
@@ -3459,7 +3462,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
// pre-rendering not supported on low-ram devices.
|
// pre-rendering not supported on low-ram devices.
|
||||||
cs.shouldPreRenderIme = DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() && !mIsLowRam;
|
cs.shouldPreRenderIme = DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() && !mIsLowRam;
|
||||||
|
|
||||||
if (mCurFocusedWindow == windowToken) {
|
final boolean sameWindowFocused = mCurFocusedWindow == windowToken;
|
||||||
|
final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0;
|
||||||
|
final boolean startInputByWinGainedFocus =
|
||||||
|
(startInputFlags & StartInputFlags.WINDOW_GAINED_FOCUS) != 0;
|
||||||
|
|
||||||
|
if (sameWindowFocused && isTextEditor) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
|
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
|
||||||
+ " attribute=" + attribute + ", token = " + windowToken
|
+ " attribute=" + attribute + ", token = " + windowToken
|
||||||
@@ -3474,6 +3482,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
|
InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
|
||||||
null, null, null, -1, null);
|
null, null, null, -1, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurFocusedWindow = windowToken;
|
mCurFocusedWindow = windowToken;
|
||||||
mCurFocusedWindowSoftInputMode = softInputMode;
|
mCurFocusedWindowSoftInputMode = softInputMode;
|
||||||
mCurFocusedWindowClient = cs;
|
mCurFocusedWindowClient = cs;
|
||||||
@@ -3491,7 +3500,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
== LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|
== LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|
||||||
|| mRes.getConfiguration().isLayoutSizeAtLeast(
|
|| mRes.getConfiguration().isLayoutSizeAtLeast(
|
||||||
Configuration.SCREENLAYOUT_SIZE_LARGE);
|
Configuration.SCREENLAYOUT_SIZE_LARGE);
|
||||||
final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0;
|
|
||||||
|
|
||||||
// We want to start input before showing the IME, but after closing
|
// We want to start input before showing the IME, but after closing
|
||||||
// it. We want to do this after closing it to help the IME disappear
|
// it. We want to do this after closing it to help the IME disappear
|
||||||
@@ -3502,7 +3510,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
InputBindResult res = null;
|
InputBindResult res = null;
|
||||||
switch (softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE) {
|
switch (softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE) {
|
||||||
case LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
|
case LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
|
||||||
if (!isTextEditor || !doAutoShow) {
|
if (!sameWindowFocused && (!isTextEditor || !doAutoShow)) {
|
||||||
if (LayoutParams.mayUseInputMethod(windowFlags)) {
|
if (LayoutParams.mayUseInputMethod(windowFlags)) {
|
||||||
// There is no focus view, and this window will
|
// There is no focus view, and this window will
|
||||||
// be behind any soft input window, so hide the
|
// be behind any soft input window, so hide the
|
||||||
@@ -3551,9 +3559,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
|
case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
|
||||||
if (DEBUG) Slog.v(TAG, "Window asks to hide input");
|
if (!sameWindowFocused) {
|
||||||
hideCurrentInputLocked(mCurFocusedWindow, 0, null,
|
if (DEBUG) Slog.v(TAG, "Window asks to hide input");
|
||||||
SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE);
|
hideCurrentInputLocked(mCurFocusedWindow, 0, null,
|
||||||
|
SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LayoutParams.SOFT_INPUT_STATE_VISIBLE:
|
case LayoutParams.SOFT_INPUT_STATE_VISIBLE:
|
||||||
if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
|
if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
|
||||||
@@ -3578,13 +3588,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
if (DEBUG) Slog.v(TAG, "Window asks to always show input");
|
if (DEBUG) Slog.v(TAG, "Window asks to always show input");
|
||||||
if (InputMethodUtils.isSoftInputModeStateVisibleAllowed(
|
if (InputMethodUtils.isSoftInputModeStateVisibleAllowed(
|
||||||
unverifiedTargetSdkVersion, startInputFlags)) {
|
unverifiedTargetSdkVersion, startInputFlags)) {
|
||||||
if (attribute != null) {
|
if (!sameWindowFocused) {
|
||||||
res = startInputUncheckedLocked(cs, inputContext, missingMethods,
|
if (attribute != null) {
|
||||||
attribute, startInputFlags, startInputReason);
|
res = startInputUncheckedLocked(cs, inputContext, missingMethods,
|
||||||
didStart = true;
|
attribute, startInputFlags, startInputReason);
|
||||||
|
didStart = true;
|
||||||
|
}
|
||||||
|
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||||
|
SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE);
|
||||||
}
|
}
|
||||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
|
||||||
SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE);
|
|
||||||
} else {
|
} else {
|
||||||
Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because"
|
Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because"
|
||||||
+ " there is no focused view that also returns true from"
|
+ " there is no focused view that also returns true from"
|
||||||
@@ -3595,7 +3607,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
|
|
||||||
if (!didStart) {
|
if (!didStart) {
|
||||||
if (attribute != null) {
|
if (attribute != null) {
|
||||||
if (!DebugFlags.FLAG_OPTIMIZE_START_INPUT.value()
|
if (sameWindowFocused) {
|
||||||
|
// On previous platforms, when Dialogs re-gained focus, the Activity behind
|
||||||
|
// would briefly gain focus first, and dismiss the IME.
|
||||||
|
// On R that behavior has been fixed, but unfortunately apps have come
|
||||||
|
// to rely on this behavior to hide the IME when the editor no longer has focus
|
||||||
|
// To maintain compatibility, we are now hiding the IME when we don't have
|
||||||
|
// an editor upon refocusing a window.
|
||||||
|
if (startInputByWinGainedFocus) {
|
||||||
|
hideCurrentInputLocked(mCurFocusedWindow, 0, null,
|
||||||
|
SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
|
||||||
|
}
|
||||||
|
res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
|
||||||
|
startInputFlags, startInputReason);
|
||||||
|
} else if (!DebugFlags.FLAG_OPTIMIZE_START_INPUT.value()
|
||||||
|| (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0) {
|
|| (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0) {
|
||||||
res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
|
res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
|
||||||
startInputFlags, startInputReason);
|
startInputFlags, startInputReason);
|
||||||
@@ -3609,6 +3634,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isImeVisible() {
|
||||||
|
return (mImeWindowVis & InputMethodService.IME_VISIBLE) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
|
private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
|
||||||
// TODO(yukawa): multi-display support.
|
// TODO(yukawa): multi-display support.
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
|
|||||||
Reference in New Issue
Block a user