summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java52
-rw-r--r--services/core/java/com/android/server/wm/InsetsControlTarget.java7
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java44
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java25
6 files changed, 126 insertions, 31 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c50048eeab64..04fc1d2f202b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -122,6 +122,7 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
+import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
@@ -3407,6 +3408,57 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
&& mInputMethodTarget.mActivityRecord.matchParentBounds());
}
+ /**
+ * Get IME target that should host IME when this display that is reparented to another
+ * WindowState.
+ * IME is never displayed in a child display.
+ * Use {@link WindowState#getImeControlTarget()} when IME target window
+ * which originally called
+ * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is known.
+ *
+ * @return {@link WindowState} of host that controls IME.
+ * {@code null} when {@param dc} is not a virtual display.
+ * @see DisplayContent#reparent
+ */
+ @Nullable
+ WindowState getImeControlTarget() {
+ WindowState imeTarget = mInputMethodTarget;
+ if (imeTarget != null) {
+ return imeTarget.getImeControlTarget();
+ }
+
+ return getInsetsStateController().getImeSourceProvider().getControlTarget().getWindow();
+ }
+
+ /**
+ * Finds the window which can host IME if IME target cannot host it.
+ * e.g. IME target cannot host IME when it's display has a parent display OR when display
+ * doesn't support IME/system decorations.
+ *
+ * @param target current IME target.
+ * @return {@link WindowState} that can host IME.
+ * @see DisplayContent#getImeControlTarget()
+ */
+ WindowState getImeHostOrFallback(WindowState target) {
+ if (target != null && target.getDisplayContent().canShowIme()) {
+ return target;
+ }
+
+ // host is in non-default display that doesn't support system decor, default to
+ // default display's StatusBar to control IME.
+ // TODO: (b/148234093)find a better host OR control IME animation/visibility directly
+ // because it won't work when statusbar isn't available.
+ return mWmService.getDefaultDisplayContentLocked().getDisplayPolicy().getStatusBar();
+ }
+
+ boolean canShowIme() {
+ if (isUntrustedVirtualDisplay()) {
+ return false;
+ }
+ return mWmService.mDisplayWindowSettings.shouldShowImeLocked(this)
+ || mWmService.mForceDesktopModeOnExternalDisplays;
+ }
+
private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
return;
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 154cde140810..20e8f2ba485a 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -26,6 +26,13 @@ interface InsetsControlTarget {
void notifyInsetsControlChanged();
/**
+ * @return {@link WindowState} of this target, if any.
+ */
+ default WindowState getWindow() {
+ return null;
+ }
+
+ /**
* Instructs the control target to show inset sources.
*
* @param types to specify which types of insets source window should be shown.
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 2bb58ddc5b38..74f6b387f5eb 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -209,6 +209,12 @@ class InsetsSourceProvider {
// to control the window for now.
return;
}
+ if (target != null && target.getWindow() != null) {
+ // ime control target could be a different window.
+ // Refer WindowState#getImeControlTarget().
+ target = target.getWindow().getImeControlTarget();
+ }
+
if (mWin == null) {
mControlTarget = target;
return;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2c6c756dda3b..f15e9eb80403 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6991,8 +6991,15 @@ public class WindowManagerService extends IWindowManager.Stub
throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
}
boolean show;
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+ if (dc == null) {
+ ProtoLog.w(WM_ERROR,
+ "Attempted to get IME flag of a display that does not exist: %d",
+ displayId);
+ return false;
+ }
synchronized (mGlobalLock) {
- show = shouldShowImeSystemWindowUncheckedLocked(displayId);
+ show = dc.canShowIme();
}
return show;
@@ -7405,15 +7412,13 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void showImePostLayout(IBinder imeTargetWindowToken) {
synchronized (mGlobalLock) {
- final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
+ WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
if (imeTarget == null) {
return;
}
- final int displayId = imeTarget.getDisplayId();
- if (!shouldShowImeSystemWindowUncheckedLocked(displayId)) {
- return;
- }
+ imeTarget = imeTarget.getImeControlTarget();
+ final int displayId = imeTarget.getDisplayId();
mRoot.getDisplayContent(displayId).getInsetsStateController().getImeSourceProvider()
.scheduleShowImePostLayout(imeTarget);
}
@@ -7423,12 +7428,16 @@ public class WindowManagerService extends IWindowManager.Stub
public void hideIme(int displayId) {
synchronized (mGlobalLock) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc != null && dc.mInputMethodTarget != null) {
+ if (dc != null) {
+ WindowState imeTarget = dc.getImeControlTarget();
+ if (imeTarget == null) {
+ return;
+ }
// If there was a pending IME show(), reset it as IME has been
// requested to be hidden.
- dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
- dc.mInputMethodControlTarget.hideInsets(WindowInsets.Type.ime(),
- true /* fromIme */);
+ imeTarget.getDisplayContent().getInsetsStateController().getImeSourceProvider()
+ .abortShowImePostLayout();
+ imeTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
}
}
}
@@ -7936,21 +7945,6 @@ public class WindowManagerService extends IWindowManager.Stub
return true;
}
- private boolean shouldShowImeSystemWindowUncheckedLocked(final int displayId) {
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- if (displayContent == null) {
- ProtoLog.w(WM_ERROR,
- "Attempted to get IME flag of a display that does not exist: %d",
- displayId);
- return false;
- }
- if (displayContent.isUntrustedVirtualDisplay()) {
- return false;
- }
- return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
- || mForceDesktopModeOnExternalDisplays;
- }
-
@Override
public void getWindowInsets(WindowManager.LayoutParams attrs,
int displayId, Rect outContentInsets, Rect outStableInsets,
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 874a25e50ae6..47d808e6f045 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3518,6 +3518,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
@Override
+ public WindowState getWindow() {
+ return this;
+ }
+
+ @Override
public void showInsets(@InsetsType int types, boolean fromIme) {
try {
mClient.showInsets(types, fromIme);
@@ -5334,6 +5339,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return false;
}
+ /**
+ * Get IME target that should host IME when this window's display has a parent.
+ * Note: IME is never hosted by a display that has a parent.
+ * When window calling
+ * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is unknown,
+ * use {@link DisplayContent#getImeControlTarget()} instead.
+ *
+ * @return {@link WindowState} of host that controls the IME.
+ * When window is doesn't have a parent, it is returned as-is.
+ */
+ WindowState getImeControlTarget() {
+ final DisplayContent dc = getDisplayContent();
+ final WindowState parentWindow = dc.getParentWindow();
+
+ // If target's display has a parent, IME is displayed in the parent display.
+ return dc.getImeHostOrFallback(parentWindow != null ? parentWindow : this);
+ }
+
@Override
void assignLayer(Transaction t, int layer) {
// See comment in assignRelativeLayerForImeTargetChild
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 20eab5a45ff1..8e362ae4c59a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -110,7 +110,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
beforeCreateDisplay();
context.getDisplay().getDisplayInfo(mDisplayInfo);
- mDisplayContent = createNewDisplay();
+ mDisplayContent = createNewDisplay(true /* supportIme */);
// Set-up some common windows.
mCommonWindows = new HashSet<>();
@@ -349,16 +349,29 @@ class WindowTestsBase extends SystemServiceTestsBase {
return WindowTestUtils.createTaskInStack(mWm, stack, userId);
}
- /** Creates a {@link DisplayContent} and adds it to the system. */
+ /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
DisplayContent createNewDisplay() {
- return createNewDisplay(mDisplayInfo);
+ return createNewDisplay(true /* supportIme */);
}
/** Creates a {@link DisplayContent} and adds it to the system. */
+ private DisplayContent createNewDisplay(boolean supportIme) {
+ return createNewDisplay(mDisplayInfo, supportIme);
+ }
+
+ /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
DisplayContent createNewDisplay(DisplayInfo info) {
+ return createNewDisplay(info, true /* supportIme */);
+ }
+
+ /** Creates a {@link DisplayContent} and adds it to the system. */
+ private DisplayContent createNewDisplay(DisplayInfo info, boolean supportIme) {
final DisplayContent display =
new TestDisplayContent.Builder(mWm.mAtmService, info).build();
- return display.mDisplayContent;
+ final DisplayContent dc = display.mDisplayContent;
+ // this display can show IME.
+ dc.mWmService.mDisplayWindowSettings.setShouldShowImeLocked(dc, supportIme);
+ return dc;
}
/**
@@ -372,7 +385,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
DisplayInfo displayInfo = new DisplayInfo();
displayInfo.copyFrom(mDisplayInfo);
displayInfo.state = displayState;
- return createNewDisplay(displayInfo);
+ return createNewDisplay(displayInfo, true /* supportIme */);
}
/** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
@@ -389,7 +402,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
displayInfo.copyFrom(mDisplayInfo);
displayInfo.type = Display.TYPE_VIRTUAL;
displayInfo.ownerUid = SYSTEM_UID;
- return createNewDisplay(displayInfo);
+ return createNewDisplay(displayInfo, false /* supportIme */);
}
/** Sets the default minimum task size to 1 so that tests can use small task sizes */