diff options
5 files changed, 62 insertions, 43 deletions
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java index 2e44b6d424cf..7d485271e35c 100644 --- a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java +++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java @@ -32,6 +32,7 @@ import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SH import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.os.IBinder; import android.os.ResultReceiver; import android.util.EventLog; @@ -137,15 +138,17 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier { @GuardedBy("ImfLock.class") @Override public void applyImeVisibility(IBinder windowToken, @NonNull ImeTracker.Token statsToken, - @ImeVisibilityStateComputer.VisibilityState int state) { + @ImeVisibilityStateComputer.VisibilityState int state, @UserIdInt int userId) { applyImeVisibility(windowToken, statsToken, state, - SoftInputShowHideReason.NOT_SET /* ignore reason */); + SoftInputShowHideReason.NOT_SET /* ignore reason */, userId); } @GuardedBy("ImfLock.class") void applyImeVisibility(IBinder windowToken, @Nullable ImeTracker.Token statsToken, @ImeVisibilityStateComputer.VisibilityState int state, - @SoftInputShowHideReason int reason) { + @SoftInputShowHideReason int reason, @UserIdInt int userId) { + final var bindingController = mService.getInputMethodBindingController(userId); + final int displayIdToShowIme = bindingController.getDisplayIdToShowIme(); switch (state) { case STATE_SHOW_IME: if (!Flags.refactorInsetsController()) { @@ -165,8 +168,7 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier { // NOT_FOCUSABLE, ALT_FOCUSABLE_IM flags set and can the IME target. // Send it to window manager to hide IME from the actual IME control target // of the target display. - mWindowManagerInternal.hideIme(windowToken, - mService.getDisplayIdToShowImeLocked(), statsToken); + mWindowManagerInternal.hideIme(windowToken, displayIdToShowIme, statsToken); } else { ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY); @@ -201,10 +203,10 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier { } break; case STATE_SHOW_IME_SNAPSHOT: - showImeScreenshot(windowToken, mService.getDisplayIdToShowImeLocked()); + showImeScreenshot(windowToken, displayIdToShowIme); break; case STATE_REMOVE_IME_SNAPSHOT: - removeImeScreenshot(mService.getDisplayIdToShowImeLocked()); + removeImeScreenshot(displayIdToShowIme); break; default: throw new IllegalArgumentException("Invalid IME visibility state: " + state); diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java index 9f2b84d9bfa5..a5f9b7a986c9 100644 --- a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java +++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java @@ -17,6 +17,7 @@ package com.android.server.inputmethod; import android.annotation.NonNull; +import android.annotation.UserIdInt; import android.os.IBinder; import android.os.ResultReceiver; import android.view.inputmethod.ImeTracker; @@ -63,7 +64,7 @@ interface ImeVisibilityApplier { * @param state The new IME visibility state for the applier to handle */ default void applyImeVisibility(IBinder windowToken, @NonNull ImeTracker.Token statsToken, - @ImeVisibilityStateComputer.VisibilityState int state) {} + @ImeVisibilityStateComputer.VisibilityState int state, @UserIdInt int userId) {} /** * Updates the IME Z-ordering relative to the given window. diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java index 8191ee14adff..3d75c48311b2 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java @@ -18,6 +18,7 @@ package com.android.server.inputmethod; import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; +import static android.view.Display.INVALID_DISPLAY; import android.annotation.NonNull; import android.annotation.Nullable; @@ -82,12 +83,15 @@ final class InputMethodBindingController { @GuardedBy("ImfLock.class") @Nullable private IInputMethodInvoker mCurMethod; @GuardedBy("ImfLock.class") private int mCurMethodUid = Process.INVALID_UID; @GuardedBy("ImfLock.class") @Nullable private IBinder mCurToken; - @GuardedBy("ImfLock.class") private int mCurTokenDisplayId = Display.INVALID_DISPLAY; + @GuardedBy("ImfLock.class") private int mCurTokenDisplayId = INVALID_DISPLAY; @GuardedBy("ImfLock.class") private int mCurSeq; @GuardedBy("ImfLock.class") private boolean mVisibleBound; @GuardedBy("ImfLock.class") private boolean mSupportsStylusHw; @GuardedBy("ImfLock.class") private boolean mSupportsConnectionlessStylusHw; + /** The display id for which the latest startInput was called. */ + @GuardedBy("ImfLock.class") private int mDisplayIdToShowIme = INVALID_DISPLAY; + @Nullable private CountDownLatch mLatchForTesting; /** @@ -455,7 +459,7 @@ final class InputMethodBindingController { mWindowManagerInternal.removeWindowToken(mCurToken, true /* removeWindows */, false /* animateExit */, mCurTokenDisplayId); mCurToken = null; - mCurTokenDisplayId = Display.INVALID_DISPLAY; + mCurTokenDisplayId = INVALID_DISPLAY; } @GuardedBy("ImfLock.class") @@ -478,16 +482,15 @@ final class InputMethodBindingController { mCurId = info.getId(); mLastBindTime = SystemClock.uptimeMillis(); - final int displayIdToShowIme = mService.getDisplayIdToShowImeLocked(); mCurToken = new Binder(); - mCurTokenDisplayId = displayIdToShowIme; + mCurTokenDisplayId = mDisplayIdToShowIme; if (DEBUG) { Slog.v(TAG, "Adding window token: " + mCurToken + " for display: " - + displayIdToShowIme); + + mDisplayIdToShowIme); } mWindowManagerInternal.addWindowToken(mCurToken, WindowManager.LayoutParams.TYPE_INPUT_METHOD, - displayIdToShowIme, null /* options */); + mDisplayIdToShowIme, null /* options */); return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING, null, null, null, mCurId, mCurSeq, false); @@ -596,4 +599,14 @@ final class InputMethodBindingController { unbindVisibleConnection(); } } + + @GuardedBy("ImfLock.class") + void setDisplayIdToShowIme(int displayId) { + mDisplayIdToShowIme = displayId; + } + + @GuardedBy("ImfLock.class") + int getDisplayIdToShowIme() { + return mDisplayIdToShowIme; + } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 8665a396c32b..48d0174ad38e 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -373,18 +373,6 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @GuardedBy("ImfLock.class") private int mMethodMapUpdateCount = 0; - /** - * The display id for which the latest startInput was called. - */ - @GuardedBy("ImfLock.class") - int getDisplayIdToShowImeLocked() { - return mDisplayIdToShowIme; - } - - @GuardedBy("ImfLock.class") - @MultiUserUnawareField - private int mDisplayIdToShowIme = INVALID_DISPLAY; - @GuardedBy("ImfLock.class") @MultiUserUnawareField private int mDeviceIdToShowIme = DEVICE_ID_DEFAULT; @@ -1951,7 +1939,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. final var statsToken = createStatsTokenForFocusedClient(false /* show */, SoftInputShowHideReason.UNBIND_CURRENT_METHOD); mVisibilityApplier.applyImeVisibility(mImeBindingState.mFocusedWindow, statsToken, - STATE_HIDE_IME); + STATE_HIDE_IME, mCurrentUserId); } } @@ -2122,7 +2110,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. return InputBindResult.NOT_IME_TARGET_WINDOW; } final int csDisplayId = cs.mSelfReportedDisplayId; - mDisplayIdToShowIme = mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId); + bindingController.setDisplayIdToShowIme( + mVisibilityStateComputer.computeImeDisplayId(winState, csDisplayId)); // Potentially override the selected input method if the new display belongs to a virtual // device with a custom IME. @@ -2193,8 +2182,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. // We expect the caller has already verified that the client is allowed to access this // display ID. final String curId = bindingController.getCurId(); + final int displayIdToShowIme = bindingController.getDisplayIdToShowIme(); if (curId != null && curId.equals(bindingController.getSelectedMethodId()) - && mDisplayIdToShowIme == getCurTokenDisplayIdLocked()) { + && displayIdToShowIme == getCurTokenDisplayIdLocked()) { if (cs.mCurSession != null) { // Fast case: if we are already connected to the input method, // then just return it. @@ -2245,7 +2235,9 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. final InputMethodSettings settings = InputMethodSettingsRepository.get(userId); final int oldDeviceId = mDeviceIdToShowIme; - mDeviceIdToShowIme = mVdmInternal.getDeviceIdForDisplayId(mDisplayIdToShowIme); + final var bindingController = getInputMethodBindingController(userId); + final int displayIdToShowIme = bindingController.getDisplayIdToShowIme(); + mDeviceIdToShowIme = mVdmInternal.getDeviceIdForDisplayId(displayIdToShowIme); if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) { if (oldDeviceId == DEVICE_ID_DEFAULT) { return currentMethodId; @@ -2279,7 +2271,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. if (DEBUG) { Slog.v(TAG, "Switching current input method from " + currentMethodId + " to device-specific one " + deviceMethodId + " because the current display " - + mDisplayIdToShowIme + " belongs to device with id " + mDeviceIdToShowIme); + + displayIdToShowIme + " belongs to device with id " + mDeviceIdToShowIme); } return deviceMethodId; } @@ -4653,7 +4645,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. windowToken); mVisibilityApplier.applyImeVisibility(requestToken, statsToken, setVisible ? ImeVisibilityStateComputer.STATE_SHOW_IME - : ImeVisibilityStateComputer.STATE_HIDE_IME); + : ImeVisibilityStateComputer.STATE_HIDE_IME, mCurrentUserId); } } finally { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); @@ -5446,7 +5438,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. @GuardedBy("ImfLock.class") private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) { mDeviceIdToShowIme = DEVICE_ID_DEFAULT; - mDisplayIdToShowIme = INVALID_DISPLAY; + final var bindingController = getInputMethodBindingController(mCurrentUserId); + bindingController.setDisplayIdToShowIme(INVALID_DISPLAY); final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId); settings.putSelectedDefaultDeviceInputMethod(null); diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java index 221a99102daa..a4ca317ce914 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java @@ -68,12 +68,15 @@ import org.junit.runner.RunWith; public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTestBase { private DefaultImeVisibilityApplier mVisibilityApplier; + private int mUserId = 0; + @Before public void setUp() throws RemoteException { super.setUp(); mVisibilityApplier = (DefaultImeVisibilityApplier) mInputMethodManagerService.getVisibilityApplier(); synchronized (ImfLock.class) { + mUserId = mInputMethodManagerService.getCurrentImeUserIdLocked(); mInputMethodManagerService.setAttachedClientForTesting(requireNonNull( mInputMethodManagerService.getClientStateLocked(mMockInputMethodClient))); } @@ -103,7 +106,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe assertThrows(IllegalArgumentException.class, () -> { synchronized (ImfLock.class) { mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(), - STATE_INVALID); + STATE_INVALID, mUserId); } }); } @@ -112,7 +115,8 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe public void testApplyImeVisibility_showIme() { final var statsToken = ImeTracker.Token.empty(); synchronized (ImfLock.class) { - mVisibilityApplier.applyImeVisibility(mWindowToken, statsToken, STATE_SHOW_IME); + mVisibilityApplier.applyImeVisibility(mWindowToken, statsToken, STATE_SHOW_IME, + mUserId); } verify(mMockWindowManagerInternal).showImePostLayout(eq(mWindowToken), eq(statsToken)); } @@ -121,7 +125,8 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe public void testApplyImeVisibility_hideIme() { final var statsToken = ImeTracker.Token.empty(); synchronized (ImfLock.class) { - mVisibilityApplier.applyImeVisibility(mWindowToken, statsToken, STATE_HIDE_IME); + mVisibilityApplier.applyImeVisibility(mWindowToken, statsToken, STATE_HIDE_IME, + mUserId); } verify(mMockWindowManagerInternal).hideIme(eq(mWindowToken), anyInt() /* displayId */, eq(statsToken)); @@ -132,7 +137,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe mInputMethodManagerService.mImeWindowVis = IME_ACTIVE; synchronized (ImfLock.class) { mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(), - STATE_HIDE_IME_EXPLICIT); + STATE_HIDE_IME_EXPLICIT, mUserId); } verifyHideSoftInput(true, true); } @@ -142,7 +147,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe mInputMethodManagerService.mImeWindowVis = IME_ACTIVE; synchronized (ImfLock.class) { mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(), - STATE_HIDE_IME_NOT_ALWAYS); + STATE_HIDE_IME_NOT_ALWAYS, mUserId); } verifyHideSoftInput(true, true); } @@ -151,7 +156,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe public void testApplyImeVisibility_showImeImplicit() throws Exception { synchronized (ImfLock.class) { mVisibilityApplier.applyImeVisibility(mWindowToken, ImeTracker.Token.empty(), - STATE_SHOW_IME_IMPLICIT); + STATE_SHOW_IME_IMPLICIT, mUserId); } verifyShowSoftInput(true, true, 0 /* showFlags */); } @@ -166,10 +171,13 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe final var statsToken = ImeTracker.Token.empty(); synchronized (ImfLock.class) { - final int displayIdToShowIme = mInputMethodManagerService.getDisplayIdToShowImeLocked(); + final var bindingController = + mInputMethodManagerService.getInputMethodBindingController(mUserId); + final int displayIdToShowIme = bindingController.getDisplayIdToShowIme(); // Verify hideIme will apply the expected displayId when the default IME // visibility applier app STATE_HIDE_IME. - mVisibilityApplier.applyImeVisibility(mWindowToken, statsToken, STATE_HIDE_IME); + mVisibilityApplier.applyImeVisibility(mWindowToken, statsToken, STATE_HIDE_IME, + mUserId); verify(mInputMethodManagerService.mWindowManagerInternal).hideIme( eq(mWindowToken), eq(displayIdToShowIme), eq(statsToken)); } @@ -204,7 +212,9 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe // 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 var statsToken = ImeTracker.Token.empty(); - final int displayIdToShowIme = mInputMethodManagerService.getDisplayIdToShowImeLocked(); + final var bindingController = + mInputMethodManagerService.getInputMethodBindingController(mUserId); + final int displayIdToShowIme = bindingController.getDisplayIdToShowIme(); mInputMethodManagerService.hideCurrentInputLocked(mWindowToken, statsToken, 0 /* flags */, null /* resultReceiver */, HIDE_SWITCH_USER); @@ -214,7 +224,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe // the IME hidden state. // The unbind will cancel the previous stats token, and create a new one internally. verify(mVisibilityApplier).applyImeVisibility( - eq(mWindowToken), any(), eq(STATE_HIDE_IME)); + eq(mWindowToken), any(), eq(STATE_HIDE_IME), eq(mUserId) /* userId */); verify(mInputMethodManagerService.mWindowManagerInternal).hideIme( eq(mWindowToken), eq(displayIdToShowIme), and(not(eq(statsToken)), notNull())); } |