summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/proto/android/server/inputmethod/inputmethodmanagerservice.proto2
-rw-r--r--services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java44
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodBindingController.java2
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java36
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java6
6 files changed, 68 insertions, 31 deletions
diff --git a/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto b/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto
index 35aae8f92d93..5a18d9e627e8 100644
--- a/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto
+++ b/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto
@@ -31,7 +31,7 @@ message InputMethodManagerServiceProto {
optional string cur_focused_window_soft_input_mode = 6;
optional .android.view.inputmethod.EditorInfoProto cur_attribute = 7;
optional string cur_id = 8;
- optional bool show_requested = 9;
+ reserved 9; // deprecated show_requested
optional bool show_explicitly_requested = 10;
optional bool show_forced = 11;
optional bool input_shown = 12;
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index 9bc91b849cc9..795e4bf9d5cb 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -254,9 +254,16 @@ public final class ImeVisibilityStateComputer {
* {@link #STATE_HIDE_IME}.
*/
void requestImeVisibility(IBinder windowToken, boolean showIme) {
- final ImeTargetWindowState state = getOrCreateWindowState(windowToken);
- state.setRequestedImeVisible(showIme);
- setWindowState(windowToken, state);
+ ImeTargetWindowState state = getOrCreateWindowState(windowToken);
+ if (!mPolicy.mPendingA11yRequestingHideKeyboard) {
+ state.setRequestedImeVisible(showIme);
+ } else {
+ // As A11y requests no IME is just a temporary, so we don't change the requested IME
+ // visible in case the last visibility state goes wrong after leaving from the a11y
+ // policy.
+ mPolicy.mPendingA11yRequestingHideKeyboard = false;
+ }
+ setWindowStateInner(windowToken, state);
}
ImeTargetWindowState getOrCreateWindowState(IBinder windowToken) {
@@ -276,12 +283,22 @@ public final class ImeVisibilityStateComputer {
ImeTargetWindowState state = getWindowStateOrNull(windowToken);
if (state != null) {
state.setRequestImeToken(token);
- setWindowState(windowToken, state);
+ setWindowStateInner(windowToken, state);
+ }
+ }
+
+ void setWindowState(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
+ final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
+ if (state != null && newState.hasEdiorFocused()) {
+ // Inherit the last requested IME visible state when the target window is still
+ // focused with an editor.
+ newState.setRequestedImeVisible(state.mRequestedImeVisible);
}
+ setWindowStateInner(windowToken, newState);
}
- void setWindowState(IBinder windowToken, ImeTargetWindowState newState) {
- if (DEBUG) Slog.d(TAG, "setWindowState, windowToken=" + windowToken
+ private void setWindowStateInner(IBinder windowToken, @NonNull ImeTargetWindowState newState) {
+ if (DEBUG) Slog.d(TAG, "setWindowStateInner, windowToken=" + windowToken
+ ", state=" + newState);
mRequestWindowStateMap.put(windowToken, newState);
}
@@ -330,6 +347,10 @@ public final class ImeVisibilityStateComputer {
// UI for input.
if (state.hasEdiorFocused() && shouldRestoreImeVisibility(state)) {
if (DEBUG) Slog.v(TAG, "Will show input to restore visibility");
+ // Inherit the last requested IME visible state when the target window is still
+ // focused with an editor.
+ state.setRequestedImeVisible(true);
+ setWindowStateInner(getWindowTokenFrom(state), state);
return new ImeVisibilityResult(STATE_SHOW_IME_IMPLICIT,
SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY);
}
@@ -512,6 +533,14 @@ public final class ImeVisibilityStateComputer {
*/
private boolean mA11yRequestingNoSoftKeyboard;
+ /**
+ * Used when A11y request to hide IME temporary when receiving
+ * {@link AccessibilityService#SHOW_MODE_HIDDEN} from
+ * {@link android.provider.Settings.Secure#ACCESSIBILITY_SOFT_KEYBOARD_MODE} without
+ * changing the requested IME visible state.
+ */
+ private boolean mPendingA11yRequestingHideKeyboard;
+
void setImeHiddenByDisplayPolicy(boolean hideIme) {
mImeHiddenByDisplayPolicy = hideIme;
}
@@ -523,6 +552,9 @@ public final class ImeVisibilityStateComputer {
void setA11yRequestNoSoftKeyboard(int keyboardShowMode) {
mA11yRequestingNoSoftKeyboard =
(keyboardShowMode & AccessibilityService.SHOW_MODE_MASK) == SHOW_MODE_HIDDEN;
+ if (mA11yRequestingNoSoftKeyboard) {
+ mPendingA11yRequestingHideKeyboard = true;
+ }
}
boolean isA11yRequestNoSoftKeyboard() {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index 079234c2f95c..187de930cff3 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -350,7 +350,7 @@ final class InputMethodBindingController {
// should now try to restart the service for us.
mLastBindTime = SystemClock.uptimeMillis();
clearCurMethodAndSessions();
- mService.clearInputShowRequestLocked();
+ mService.clearInputShownLocked();
mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME);
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 076673651490..a94c90c8ee63 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -38,7 +38,6 @@ import static android.server.inputmethod.InputMethodManagerServiceProto.IS_INTER
import static android.server.inputmethod.InputMethodManagerServiceProto.LAST_IME_TARGET_WINDOW_NAME;
import static android.server.inputmethod.InputMethodManagerServiceProto.LAST_SWITCH_USER_ID;
import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_IME_WITH_HARD_KEYBOARD;
-import static android.server.inputmethod.InputMethodManagerServiceProto.SHOW_REQUESTED;
import static android.server.inputmethod.InputMethodManagerServiceProto.SYSTEM_READY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -623,11 +622,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
return mBindingController.hasConnection();
}
- /**
- * Set if the client has asked for the input method to be shown.
- */
- private boolean mShowRequested;
-
/** The token tracking the current IME request or {@code null} otherwise. */
@Nullable
private ImeTracker.Token mCurStatsToken;
@@ -1168,12 +1162,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mVisibilityStateComputer.getImePolicy().setA11yRequestNoSoftKeyboard(
accessibilitySoftKeyboardSetting);
if (mVisibilityStateComputer.getImePolicy().isA11yRequestNoSoftKeyboard()) {
- final boolean showRequested = mShowRequested;
hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */,
0 /* flags */, null /* resultReceiver */,
SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE);
- mShowRequested = showRequested;
- } else if (mShowRequested) {
+ } else if (isShowRequestedForCurrentWindow()) {
showCurrentInputImplicitLocked(mCurFocusedWindow,
SoftInputShowHideReason.SHOW_SETTINGS_ON_CHANGE);
}
@@ -2293,8 +2285,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@GuardedBy("ImfLock.class")
- void clearInputShowRequestLocked() {
- mShowRequested = mVisibilityStateComputer.isInputShown();
+ void clearInputShownLocked() {
mVisibilityStateComputer.setInputShown(false);
}
@@ -2304,6 +2295,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@GuardedBy("ImfLock.class")
+ private boolean isShowRequestedForCurrentWindow() {
+ final ImeTargetWindowState state = mVisibilityStateComputer.getWindowStateOrNull(
+ mCurFocusedWindow);
+ return state != null && state.isRequestedImeVisible();
+ }
+
+ @GuardedBy("ImfLock.class")
@NonNull
InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) {
if (!mBoundToMethod) {
@@ -2339,7 +2337,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
setEnabledSessionLocked(session);
session.mMethod.startInput(startInputToken, mCurInputConnection, mCurEditorInfo, restarting,
navButtonFlags, mCurImeDispatcher);
- if (mShowRequested) {
+ if (isShowRequestedForCurrentWindow()) {
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
// Re-use current statsToken, if it exists.
final ImeTracker.Token statsToken = mCurStatsToken;
@@ -2558,7 +2556,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
if (!mPreventImeStartupUnlessTextEditor) {
return false;
}
- if (mShowRequested) {
+ if (isShowRequestedForCurrentWindow()) {
return false;
}
if (isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags)) {
@@ -3369,9 +3367,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
ImeTracker.ORIGIN_SERVER_START_INPUT, reason);
}
- // TODO(b/246309664): make mShowRequested as per-window state.
- mShowRequested = true;
-
if (!mVisibilityStateComputer.onImeShowFlags(statsToken, flags)) {
return false;
}
@@ -3466,7 +3461,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// application process as a valid request, and have even promised such a behavior with CTS
// since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only
// IMMS#InputShown indicates that the software keyboard is shown.
- // TODO(b/246309664): Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
+ // TODO(b/246309664): Clean up IMMS#mImeWindowVis
IInputMethodInvoker curMethod = getCurMethodLocked();
final boolean shouldHideSoftInput = curMethod != null
&& (isInputShown() || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
@@ -3484,7 +3479,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
mBindingController.setCurrentMethodNotVisible();
mVisibilityStateComputer.clearImeShowFlags();
- mShowRequested = false;
// Cancel existing statsToken for show IME as we got a hide request.
ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = null;
@@ -3699,7 +3693,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
final ImeVisibilityResult imeVisRes = mVisibilityStateComputer.computeState(windowState,
isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags));
if (imeVisRes != null) {
- switch(imeVisRes.getReason()) {
+ switch (imeVisRes.getReason()) {
case SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY:
case SoftInputShowHideReason.SHOW_AUTO_EDITOR_FORWARD_NAV:
case SoftInputShowHideReason.SHOW_STATE_VISIBLE_FORWARD_NAV:
@@ -4502,7 +4496,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mCurEditorInfo.dumpDebug(proto, CUR_ATTRIBUTE);
}
proto.write(CUR_ID, getCurIdLocked());
- proto.write(SHOW_REQUESTED, mShowRequested);
mVisibilityStateComputer.dumpDebug(proto, fieldId);
proto.write(IN_FULLSCREEN_MODE, mInFullscreenMode);
proto.write(CUR_TOKEN, Objects.toString(getCurTokenLocked()));
@@ -4750,7 +4743,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
synchronized (ImfLock.class) {
try {
if (mEnabledSession != null && mEnabledSession.mSession != null
- && !mShowRequested) {
+ && !isShowRequestedForCurrentWindow()) {
mEnabledSession.mSession.removeImeSurface();
}
} catch (RemoteException e) {
@@ -5738,7 +5731,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
method = getCurMethodLocked();
p.println(" mCurMethod=" + getCurMethodLocked());
p.println(" mEnabledSession=" + mEnabledSession);
- p.println(" mShowRequested=" + mShowRequested);
mVisibilityStateComputer.dump(pw);
p.println(" mInFullscreenMode=" + mInFullscreenMode);
p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 841094221d99..66f6a3fb5cc0 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -9360,6 +9360,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
configChangeFlags = 0;
return;
}
+ if (!preserveWindow) {
+ // If the activity is the IME input target, ensure storing the last IME shown state
+ // before relaunching it for restoring the IME visibility once its new window focused.
+ final InputTarget imeInputTarget = mDisplayContent.getImeInputTarget();
+ mLastImeShown = imeInputTarget != null && imeInputTarget.getWindowState() != null
+ && imeInputTarget.getWindowState().mActivityRecord == this
+ && mDisplayContent.mInputMethodWindow != null
+ && mDisplayContent.mInputMethodWindow.isVisible();
+ }
// Do not waiting for translucent activity if it is going to relaunch.
final Task rootTask = getRootTask();
if (rootTask != null && rootTask.mTranslucentActivityWaiting == this) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 79830477ea3d..9b845cd8285e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -9139,6 +9139,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean shouldRestoreImeVisibility(IBinder imeTargetWindowToken) {
final Task imeTargetWindowTask;
+ boolean hadRequestedShowIme = false;
synchronized (mGlobalLock) {
final WindowState imeTargetWindow = mWindowMap.get(imeTargetWindowToken);
if (imeTargetWindow == null) {
@@ -9148,11 +9149,14 @@ public class WindowManagerService extends IWindowManager.Stub
if (imeTargetWindowTask == null) {
return false;
}
+ if (imeTargetWindow.mActivityRecord != null) {
+ hadRequestedShowIme = imeTargetWindow.mActivityRecord.mLastImeShown;
+ }
}
final TaskSnapshot snapshot = getTaskSnapshot(imeTargetWindowTask.mTaskId,
imeTargetWindowTask.mUserId, false /* isLowResolution */,
false /* restoreFromDisk */);
- return snapshot != null && snapshot.hasImeSurface();
+ return snapshot != null && snapshot.hasImeSurface() || hadRequestedShowIme;
}
@Override