summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Cosmin Băieș <cosminbaies@google.com> 2023-09-18 12:04:45 +0200
committer Cosmin Băieș <cosminbaies@google.com> 2023-09-19 16:12:53 +0000
commit8eb7be5bf222e1f6e3ab17308725dc537e316d41 (patch)
treea0418c7c6e0d830e51827a5332e56bd439757305
parentc6d3bf6a7f80c503b44d05abf5cc29e6cab1e640 (diff)
Fix deadlock in IMMS checking hasNavigationBar
Since allowing IMEs to request hiding the fake IME navigation bar in [1], we found that this would still be shown on emulator, which has no system navigation bar, and would thus break some tests. This was fixed in [2], but it looks like that fix can trigger a deadlock as it goes through calling WindowManagerGlobal.getWindowManagerService, which tries to acquire the lock on that class. Instead, I added a path to call hasNavigationBar through WindowManagerInternal, which also skips the IPC step. This will still require the WindowManagerGlobalLock, but the internal class is currently used throughout InputMethodManagerService, so it should be safe here. [1]: I8793db69fb846046300d5a56b3b0060138ef4cd5 [2]: Ide89075836a527d806f28cbeeb8d90334b79428f Test: atest InputMethodServiceTest#testNoNavigationBar_thenImeNoCaptionBar Bug: 300359571 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:d136b9bd629295c996367ed01f96a5f3fa658dc7) Merged-In: I4d7a062a9abeaf59218505d384f94e04e1a8ed74 Change-Id: I4d7a062a9abeaf59218505d384f94e04e1a8ed74
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java5
3 files changed, 18 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 7aea63255dc8..a1d28da5f65e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -119,7 +119,6 @@ import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
-import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -127,7 +126,6 @@ import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
-import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputBinding;
@@ -3073,9 +3071,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
ConcurrentUtils.waitForFutureNoInterrupt(mImeDrawsImeNavBarResLazyInitFuture,
"Waiting for the lazy init of mImeDrawsImeNavBarRes");
}
+ // Whether the current display has a navigation bar. When this is false (e.g. emulator),
+ // the IME should not draw the IME navigation bar.
+ final boolean hasNavigationBar = mWindowManagerInternal
+ .hasNavigationBar(mCurTokenDisplayId != INVALID_DISPLAY
+ ? mCurTokenDisplayId : DEFAULT_DISPLAY);
final boolean canImeDrawsImeNavBar =
- mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get()
- && hasNavigationBarOnCurrentDisplay();
+ mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get() && hasNavigationBar;
final boolean shouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherLocked(
InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE);
return (canImeDrawsImeNavBar ? InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR : 0)
@@ -3083,21 +3085,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
? InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN : 0);
}
- /**
- * Whether the current display has a navigation bar. When this is {@code false} (e.g. emulator),
- * the IME should <em>not</em> draw the IME navigation bar.
- */
- @GuardedBy("ImfLock.class")
- private boolean hasNavigationBarOnCurrentDisplay() {
- final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
- try {
- return wm.hasNavigationBar(mCurTokenDisplayId != INVALID_DISPLAY
- ? mCurTokenDisplayId : DEFAULT_DISPLAY);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
@GuardedBy("ImfLock.class")
private boolean shouldShowImeSwitcherLocked(int visibility) {
if (!mShowOngoingImeSwitcherForPhones) return false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 805e7ffe7d76..9f1bccb9a27a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -954,4 +954,11 @@ public abstract class WindowManagerInternal {
/** Returns the SurfaceControl accessibility services should use for accessibility overlays. */
public abstract SurfaceControl getA11yOverlayLayer(int displayId);
+
+ /**
+ * Device has a software navigation bar (separate from the status bar) on specific display.
+ *
+ * @param displayId the id of display to check if there is a software navigation bar.
+ */
+ public abstract boolean hasNavigationBar(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 b20be551c114..e6a341fe37e7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8380,6 +8380,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public boolean hasNavigationBar(int displayId) {
+ return WindowManagerService.this.hasNavigationBar(displayId);
+ }
+
+ @Override
public void setInputMethodTargetChangeListener(@NonNull ImeTargetChangeListener listener) {
synchronized (mGlobalLock) {
mImeTargetChangeListener = listener;