From 18f4606d457965fc4370e78e0837071148c27fbd Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Thu, 1 Aug 2024 10:01:18 -0700 Subject: [PATCH] Propagate displayId in ImeTargetChangeListener This is a follow up CL to our previous CLs [1][2], which added ImeTargetChangeListener. To support concurrent multi-user multi-display scenarios, we need to distinguish whose IMEs these callbacks are talking about. To do so, with this CL the relevant display ID also starts being propagated into ImeVisibilityStateComputer. These display IDs are not yet used thus there must be no observable behavior change in this CL. [1]: I90c59c298e2e4568e308fb2c0dc4ca309d5546a3 f8c633712b095736a07f6e9192b0e85da53fba99 [2]: I3a950423f73f0a97432589d0a90ac8fd1c84f05e 8fb9afd6559357f6583f19b04422312749ca910e Fix: 356177006 Test: presubmit Test: atest WmTests:WindowStateTests Test: atest FrameworksInputMethodSystemServerTests Flag: EXEMPT refactor Change-Id: Ib50f7fdfb455b6d09707f680e71ad3dd7b0a18f2 --- .../ImeVisibilityStateComputer.java | 4 ++-- .../com/android/server/wm/DisplayContent.java | 5 +++-- .../server/wm/ImeTargetChangeListener.java | 8 ++++--- .../server/wm/WindowManagerService.java | 21 +++++++++++-------- .../com/android/server/wm/WindowState.java | 6 +++--- .../ImeVisibilityStateComputerTest.java | 8 ++++--- .../android/server/wm/WindowStateTests.java | 13 ++++++++++-- 7 files changed, 41 insertions(+), 24 deletions(-) diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java index 42a99defcbee..b67dd0f2a0f7 100644 --- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java +++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java @@ -220,7 +220,7 @@ public final class ImeVisibilityStateComputer { @Override public void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken, @WindowManager.LayoutParams.WindowType int windowType, boolean visible, - boolean removed) { + boolean removed, int displayId) { // Ignoring the starting window since it's ok to cover the IME target // window in temporary without affecting the IME visibility. final boolean hasOverlay = visible && !removed @@ -232,7 +232,7 @@ public final class ImeVisibilityStateComputer { @Override public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget, - boolean visibleRequested, boolean removed) { + boolean visibleRequested, boolean removed, int displayId) { final boolean visibleAndNotRemoved = visibleRequested && !removed; synchronized (ImfLock.class) { if (visibleAndNotRemoved) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 3a0de850771a..9c8c759765bc 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4415,13 +4415,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mWmService.dispatchImeInputTargetVisibilityChanged( targetWin.mClient.asBinder(), isVisibleRequested, targetWin.mActivityRecord != null - && targetWin.mActivityRecord.finishing); + && targetWin.mActivityRecord.finishing, + mDisplayId); } }); targetWin.mToken.registerWindowContainerListener( mImeTargetTokenListenerPair.second); mWmService.dispatchImeInputTargetVisibilityChanged(targetWin.mClient.asBinder(), - targetWin.isVisible() /* visible */, false /* removed */); + targetWin.isVisible() /* visible */, false /* removed */, mDisplayId); } } if (refreshImeSecureFlag(getPendingTransaction())) { diff --git a/services/core/java/com/android/server/wm/ImeTargetChangeListener.java b/services/core/java/com/android/server/wm/ImeTargetChangeListener.java index 88b76aaa6992..e94f17c37051 100644 --- a/services/core/java/com/android/server/wm/ImeTargetChangeListener.java +++ b/services/core/java/com/android/server/wm/ImeTargetChangeListener.java @@ -37,25 +37,27 @@ public interface ImeTargetChangeListener { * @param visible the visibility of the overlay window, {@code true} means visible * and {@code false} otherwise. * @param removed Whether the IME target overlay window has being removed. + * @param displayId display ID where the overlay window exists. */ default void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken, @WindowManager.LayoutParams.WindowType int windowType, - boolean visible, boolean removed) { + boolean visible, boolean removed, int displayId) { } /** * Called when the visibility of IME input target window has changed. * * @param imeInputTarget the window token of the IME input target window. - * @param visible the new window visibility made by {@param imeInputTarget}. visible is + * @param visible the new window visibility made by {@code imeInputTarget}. visible is * {@code true} when switching to the new visible IME input target * window and started input, or the same input target relayout to * visible from invisible. In contrast, visible is {@code false} when * closing the input target, or the same input target relayout to * invisible from visible. * @param removed Whether the IME input target window has being removed. + * @param displayId display ID where the overlay window exists. */ default void onImeInputTargetVisibilityChanged(@NonNull IBinder imeInputTarget, boolean visible, - boolean removed) { + boolean removed, int displayId) { } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d73d509863ab..cf92f1bbb9cf 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1897,7 +1897,8 @@ public class WindowManagerService extends IWindowManager.Stub displayContent.computeImeTarget(true /* updateImeTarget */); if (win.isImeOverlayLayeringTarget()) { dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type, - win.isVisibleRequestedOrAdding(), false /* removed */); + win.isVisibleRequestedOrAdding(), false /* removed */, + displayContent.getDisplayId()); } } @@ -2661,13 +2662,13 @@ public class WindowManagerService extends IWindowManager.Stub final boolean winVisibleChanged = win.isVisible() != wasVisible; if (win.isImeOverlayLayeringTarget() && winVisibleChanged) { dispatchImeTargetOverlayVisibilityChanged(client.asBinder(), win.mAttrs.type, - win.isVisible(), false /* removed */); + win.isVisible(), false /* removed */, win.getDisplayId()); } // Notify listeners about IME input target window visibility change. final boolean isImeInputTarget = win.getDisplayContent().getImeInputTarget() == win; if (isImeInputTarget && winVisibleChanged) { dispatchImeInputTargetVisibilityChanged(win.mClient.asBinder(), - win.isVisible() /* visible */, false /* removed */); + win.isVisible() /* visible */, false /* removed */, win.getDisplayId()); } if (outRelayoutResult != null) { @@ -3515,27 +3516,29 @@ public class WindowManagerService extends IWindowManager.Stub void dispatchImeTargetOverlayVisibilityChanged(@NonNull IBinder token, @WindowManager.LayoutParams.WindowType int windowType, boolean visible, - boolean removed) { + boolean removed, int displayId) { if (mImeTargetChangeListener != null) { if (DEBUG_INPUT_METHOD) { Slog.d(TAG, "onImeTargetOverlayVisibilityChanged, win=" + mWindowMap.get(token) + ", type=" + ViewDebug.intToString(WindowManager.LayoutParams.class, - "type", windowType) + "visible=" + visible + ", removed=" + removed); + "type", windowType) + "visible=" + visible + ", removed=" + removed + + ", displayId=" + displayId); } mH.post(() -> mImeTargetChangeListener.onImeTargetOverlayVisibilityChanged(token, - windowType, visible, removed)); + windowType, visible, removed, displayId)); } } void dispatchImeInputTargetVisibilityChanged(@NonNull IBinder token, boolean visible, - boolean removed) { + boolean removed, int displayId) { if (mImeTargetChangeListener != null) { if (DEBUG_INPUT_METHOD) { Slog.d(TAG, "onImeInputTargetVisibilityChanged, win=" + mWindowMap.get(token) - + "visible=" + visible + ", removed=" + removed); + + "visible=" + visible + ", removed=" + removed + + ", displayId" + displayId); } mH.post(() -> mImeTargetChangeListener.onImeInputTargetVisibilityChanged(token, - visible, removed)); + visible, removed, displayId)); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 153d41be4fee..a61925f7bd6c 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2359,11 +2359,11 @@ class WindowState extends WindowContainer implements WindowManagerP } super.removeImmediately(); + final DisplayContent dc = getDisplayContent(); if (isImeOverlayLayeringTarget()) { mWmService.dispatchImeTargetOverlayVisibilityChanged(mClient.asBinder(), mAttrs.type, - false /* visible */, true /* removed */); + false /* visible */, true /* removed */, dc.getDisplayId()); } - final DisplayContent dc = getDisplayContent(); if (isImeLayeringTarget()) { // Remove the attached IME screenshot surface. dc.removeImeSurfaceByTarget(this); @@ -2374,7 +2374,7 @@ class WindowState extends WindowContainer implements WindowManagerP } if (dc.getImeInputTarget() == this && !inRelaunchingActivity()) { mWmService.dispatchImeInputTargetVisibilityChanged(mClient.asBinder(), - false /* visible */, true /* removed */); + false /* visible */, true /* removed */, dc.getDisplayId()); dc.updateImeInputAndControlTarget(null); } diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java index dd3b33e0d12a..4cd3157dee87 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java @@ -302,12 +302,14 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes final IBinder testImeInputTarget = new Binder(); // Simulate a test IME input target was visible. - mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, true, false); + mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, true, false, + DEFAULT_DISPLAY); // Simulate a test IME layering target overlay fully occluded the IME input target. mListener.onImeTargetOverlayVisibilityChanged(testImeTargetOverlay, - TYPE_APPLICATION_OVERLAY, true, false); - mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, false, false); + TYPE_APPLICATION_OVERLAY, true, false, DEFAULT_DISPLAY); + mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, false, false, + DEFAULT_DISPLAY); final ArgumentCaptor targetCaptor = ArgumentCaptor.forClass(IBinder.class); final ArgumentCaptor resultCaptor = ArgumentCaptor.forClass( ImeVisibilityResult.class); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index b46189c1704a..11df331ff398 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -1351,6 +1351,7 @@ public class WindowStateTests extends WindowTestsBase { assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder()); assertThat(listener.mIsRemoved).isFalse(); assertThat(listener.mIsVisibleForImeInputTarget).isTrue(); + assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId()); imeTarget.mActivityRecord.setVisibleRequested(false); waitHandlerIdle(mWm.mH); @@ -1358,11 +1359,13 @@ public class WindowStateTests extends WindowTestsBase { assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder()); assertThat(listener.mIsRemoved).isFalse(); assertThat(listener.mIsVisibleForImeInputTarget).isFalse(); + assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId()); imeTarget.removeImmediately(); assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder()); assertThat(listener.mIsRemoved).isTrue(); assertThat(listener.mIsVisibleForImeInputTarget).isFalse(); + assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId()); } @SetupWindows(addWindows = {W_INPUT_METHOD}) @@ -1402,6 +1405,7 @@ public class WindowStateTests extends WindowTestsBase { assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder()); assertThat(listener.mIsRemoved).isFalse(); assertThat(listener.mIsVisibleForImeTargetOverlay).isTrue(); + assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId()); // Scenario 2: test relayoutWindow to let the Ime layering target overlay window invisible. mWm.relayoutWindow(session, client, params, 100, 200, View.GONE, 0, 0, 0, @@ -1412,6 +1416,7 @@ public class WindowStateTests extends WindowTestsBase { assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder()); assertThat(listener.mIsRemoved).isFalse(); assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse(); + assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId()); // Scenario 3: test removeWindow to remove the Ime layering target overlay window. mWm.removeClientToken(session, client.asBinder()); @@ -1420,6 +1425,7 @@ public class WindowStateTests extends WindowTestsBase { assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder()); assertThat(listener.mIsRemoved).isTrue(); assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse(); + assertThat(listener.mDisplayId).isEqualTo(mDisplayContent.getDisplayId()); } @Test @@ -1468,22 +1474,25 @@ public class WindowStateTests extends WindowTestsBase { private boolean mIsRemoved; private boolean mIsVisibleForImeTargetOverlay; private boolean mIsVisibleForImeInputTarget; + private int mDisplayId; @Override public void onImeTargetOverlayVisibilityChanged(IBinder overlayWindowToken, @WindowManager.LayoutParams.WindowType int windowType, boolean visible, - boolean removed) { + boolean removed, int displayId) { mImeTargetToken = overlayWindowToken; mIsVisibleForImeTargetOverlay = visible; mIsRemoved = removed; + mDisplayId = displayId; } @Override public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget, - boolean visibleRequested, boolean removed) { + boolean visibleRequested, boolean removed, int displayId) { mImeTargetToken = imeInputTarget; mIsVisibleForImeInputTarget = visibleRequested; mIsRemoved = removed; + mDisplayId = displayId; } } } -- GitLab