diff options
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 |