Merge "Fix IME insets not apply hidden when switching focus in diffrent users" into udc-qpr-dev am: ebdd8b4104

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23739364

Change-Id: I0fe771b4800e53c8219771b68f66a0a75d8f7545
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Ming-Shin Lu
2023-06-28 10:26:55 +00:00
committed by Automerger Merge Worker
2 changed files with 50 additions and 0 deletions

View File

@@ -48,6 +48,7 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeTargetWindowState; import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeTargetWindowState;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeVisibilityResult; import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeVisibilityResult;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME;
import static com.android.server.inputmethod.InputMethodBindingController.TIME_TO_RECONNECT; import static com.android.server.inputmethod.InputMethodBindingController.TIME_TO_RECONNECT;
import static com.android.server.inputmethod.InputMethodUtils.isSoftInputModeStateVisibleAllowed; import static com.android.server.inputmethod.InputMethodUtils.isSoftInputModeStateVisibleAllowed;
@@ -2367,6 +2368,28 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
} }
} }
/**
* Called when {@link #resetCurrentMethodAndClientLocked(int)} invoked for clean-up states
* before unbinding the current method.
*/
@GuardedBy("ImfLock.class")
void onUnbindCurrentMethodByReset() {
final ImeTargetWindowState winState = mVisibilityStateComputer.getWindowStateOrNull(
mCurFocusedWindow);
if (winState != null && !winState.isRequestedImeVisible()
&& !mVisibilityStateComputer.isInputShown()) {
// Normally, the focus window will apply the IME visibility state to
// WindowManager when the IME has applied it. But it would be too late when
// switching IMEs in between different users. (Since the focused IME will
// first unbind the service to switch to bind the next user of the IME
// service, that wouldn't make the attached IME token validity check in time)
// As a result, we have to notify WM to apply IME visibility before clearing the
// binding states in the first place.
mVisibilityApplier.applyImeVisibility(mCurFocusedWindow, mCurStatsToken,
STATE_HIDE_IME);
}
}
/** {@code true} when a {@link ClientState} has attached from starting the input connection. */ /** {@code true} when a {@link ClientState} has attached from starting the input connection. */
@GuardedBy("ImfLock.class") @GuardedBy("ImfLock.class")
boolean hasAttachedClient() { boolean hasAttachedClient() {
@@ -2838,6 +2861,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("ImfLock.class") @GuardedBy("ImfLock.class")
void resetCurrentMethodAndClientLocked(@UnbindReason int unbindClientReason) { void resetCurrentMethodAndClientLocked(@UnbindReason int unbindClientReason) {
setSelectedMethodIdLocked(null); setSelectedMethodIdLocked(null);
// Callback before clean-up binding states.
onUnbindCurrentMethodByReset();
mBindingController.unbindCurrentMethod(); mBindingController.unbindCurrentMethod();
unbindCurrentClientLocked(unbindClientReason); unbindCurrentClientLocked(unbindClientReason);
} }

View File

@@ -20,6 +20,7 @@ import static android.inputmethodservice.InputMethodService.IME_ACTIVE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_SOFT_INPUT; import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_SOFT_INPUT;
import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_SWITCH_USER;
import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_SOFT_INPUT; import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_SOFT_INPUT;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME; import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_EXPLICIT; import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_EXPLICIT;
@@ -43,6 +44,7 @@ import android.view.inputmethod.InputMethodManager;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.inputmethod.InputBindResult; import com.android.internal.inputmethod.InputBindResult;
import com.android.internal.inputmethod.StartInputFlags; import com.android.internal.inputmethod.StartInputFlags;
import com.android.internal.inputmethod.StartInputReason; import com.android.internal.inputmethod.StartInputReason;
@@ -165,6 +167,29 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
verify(mMockImeTargetVisibilityPolicy).removeImeScreenshot(eq(Display.DEFAULT_DISPLAY)); verify(mMockImeTargetVisibilityPolicy).removeImeScreenshot(eq(Display.DEFAULT_DISPLAY));
} }
@Test
public void testApplyImeVisibility_hideImeWhenUnbinding() {
mInputMethodManagerService.setAttachedClientForTesting(null);
startInputOrWindowGainedFocus(mWindowToken, SOFT_INPUT_STATE_ALWAYS_VISIBLE);
ExtendedMockito.spyOn(mVisibilityApplier);
synchronized (ImfLock.class) {
// Simulate the system hides the IME when switching IME services in different users.
// (e.g. unbinding the IME from the current user to the profile user)
final int displayIdToShowIme = mInputMethodManagerService.getDisplayIdToShowImeLocked();
mInputMethodManagerService.hideCurrentInputLocked(mWindowToken, null, 0, null,
HIDE_SWITCH_USER);
mInputMethodManagerService.onUnbindCurrentMethodByReset();
// Expects applyImeVisibility() -> hideIme() will be called to notify WM for syncing
// the IME hidden state.
verify(mVisibilityApplier).applyImeVisibility(eq(mWindowToken), any(),
eq(STATE_HIDE_IME));
verify(mInputMethodManagerService.mWindowManagerInternal).hideIme(
eq(mWindowToken), eq(displayIdToShowIme), eq(null));
}
}
private InputBindResult startInputOrWindowGainedFocus(IBinder windowToken, int softInputMode) { private InputBindResult startInputOrWindowGainedFocus(IBinder windowToken, int softInputMode) {
return mInputMethodManagerService.startInputOrWindowGainedFocus( return mInputMethodManagerService.startInputOrWindowGainedFocus(
StartInputReason.WINDOW_FOCUS_GAIN /* startInputReason */, StartInputReason.WINDOW_FOCUS_GAIN /* startInputReason */,