Rip out WindowContainer#isScreenOverlay
Messes up ordering of the windows that should be above
the navigation bar and status bar. It seems better to
achieve the IME layering we need directly.
Bug: 69591927
Test: Manual
Change-Id: I69202bca0b84cec5d9f5176645e31c5bd0af767e
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 409e04b..56e5922 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -181,8 +181,8 @@
private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
// Contains all non-app window containers that should be displayed above the app containers
// (e.g. Status bar)
- private final NonAppWindowContainers mAboveAppWindowsContainers =
- new NonAppWindowContainers("mAboveAppWindowsContainers");
+ private final AboveAppWindowContainers mAboveAppWindowsContainers =
+ new AboveAppWindowContainers("mAboveAppWindowsContainers");
// Contains all non-app window containers that should be displayed below the app containers
// (e.g. Wallpaper).
private final NonAppWindowContainers mBelowAppWindowsContainers =
@@ -356,7 +356,8 @@
/**
* We organize all top-level Surfaces in to the following layers.
* mOverlayLayer contains a few Surfaces which are always on top of others
- * and omitted from Screen-Magnification ({@link WindowState#isScreenOverlay})
+ * and omitted from Screen-Magnification, for example the strict mode flash or
+ * the magnification overlay itself.
* {@link #mWindowingLayer} contains everything else.
*/
private SurfaceControl mOverlayLayer;
@@ -3746,11 +3747,39 @@
}
}
+ private final class AboveAppWindowContainers extends NonAppWindowContainers {
+ AboveAppWindowContainers(String name) {
+ super(name);
+ }
+
+ void assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer) {
+ boolean needAssignIme = imeContainer != null
+ && imeContainer.getSurfaceControl() != null;
+ for (int j = 0; j < mChildren.size(); ++j) {
+ final WindowToken wt = mChildren.get(j);
+ wt.assignLayer(t, j);
+ wt.assignChildLayers(t);
+
+ int layer = mService.mPolicy.getWindowLayerFromTypeLw(
+ wt.windowType, wt.mOwnerCanManageAppTokens);
+ if (needAssignIme && layer >= TYPE_INPUT_METHOD_DIALOG) {
+ t.setRelativeLayer(imeContainer.getSurfaceControl(),
+ wt.getSurfaceControl(), -1);
+ needAssignIme = false;
+ }
+ }
+ if (needAssignIme) {
+ t.setRelativeLayer(imeContainer.getSurfaceControl(),
+ getSurfaceControl(), Integer.MIN_VALUE);
+ }
+ }
+ }
+
/**
* Window container class that contains all containers on this display that are not related to
* Apps. E.g. status bar.
*/
- private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
+ private class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
/**
* Compares two child window tokens returns -1 if the first is lesser than the second in
* terms of z-order and 1 otherwise.
@@ -3848,12 +3877,8 @@
return b;
}
- b.setName(child.getName());
- if (child.isScreenOverlay()) {
- return b.setParent(mOverlayLayer);
- } else {
- return b.setParent(mWindowingLayer);
- }
+ return b.setName(child.getName())
+ .setParent(mWindowingLayer);
}
/**
@@ -3891,39 +3916,36 @@
mAboveAppWindowsContainers.assignLayer(t, 2);
WindowState imeTarget = mService.mInputMethodTarget;
+ boolean needAssignIme = true;
- // A brief summary of IME layer assignment:
+ // In the case where we have an IME target that is not in split-screen
+ // mode IME assignment is easy. We just need the IME to go directly above
+ // the target. This way children of the target will naturally go above the IME
+ // and everyone is happy.
//
- // In case we have no IME target but we have an IME we are typically in
- // a transition state and keeping the IME on top of everything except overlays
- // seems to work best.
+ // In the case of split-screen windowing mode, we need to elevate the IME above the
+ // docked divider while keeping the app itself below the docked divider, so instead
+ // we use relative layering of the IME targets child windows, and place the
+ // IME in the non-app layer (see {@link AboveAppWindowContainers#assignChildLayers}).
//
- // In split-screen windowing mode we can't layer the
- // IME relative to the IME target because it needs to
- // go over the docked divider, so instead we place it on top
- // of everything and use relative layering of windows which need
- // to go above it (see special logic in WindowState#assignLayer)
- //
- // There is a third case, where the IME target has no SurfaceControl, for
- // example if Layer assignment were triggered due to removal of the
- // IME target while it was still the IME target.
- if (imeTarget == null ||
- imeTarget.inSplitScreenWindowingMode() ||
- imeTarget.getSurfaceControl() == null) {
- mImeWindowsContainers.assignLayer(t, 3);
- } else {
+ // In the case where we have no IME target we assign it where it's base layer would
+ // place it in the AboveAppWindowContainers.
+ if (imeTarget != null && !imeTarget.inSplitScreenWindowingMode()
+ && (imeTarget.getSurfaceControl() != null)) {
t.setRelativeLayer(mImeWindowsContainers.getSurfaceControl(),
imeTarget.getSurfaceControl(),
// TODO: We need to use an extra level on the app surface to ensure
// this is always above SurfaceView but always below attached window.
1);
+ needAssignIme = false;
}
// Above we have assigned layers to our children, now we ask them to assign
// layers to their children.
mBelowAppWindowsContainers.assignChildLayers(t);
mTaskStackContainers.assignChildLayers(t);
- mAboveAppWindowsContainers.assignChildLayers(t);
+ mAboveAppWindowsContainers.assignChildLayers(t,
+ needAssignIme == true ? mImeWindowsContainers : null);
mImeWindowsContainers.assignChildLayers(t);
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 610453e..6467582 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -731,29 +731,8 @@
final WindowContainer p = getParent();
// Give the parent a chance to set properties. In hierarchy v1 we rely
// on this to set full-screen dimensions on all our Surface-less Layers.
- final SurfaceControl.Builder b = p.makeChildSurface(child);
- if (child != null && child.isScreenOverlay()) {
- // If it's a screen overlay it's been promoted in the hierarchy (wrt to the
- // WindowContainer hierarchy vs the SurfaceControl hierarchy)
- // and we shouldn't set ourselves as the parent.
- return b;
- } else {
- return b.setParent(mSurfaceControl);
- }
- }
-
- /**
- * There are various layers which require promotion from the WindowContainer
- * hierarchy to the Overlay layer described in {@link DisplayContent}. See {@link WindowState}
- * for the particular usage.
- *
- * TODO: Perhaps this should be eliminated, either through modifying
- * the window container hierarchy or through modifying the way we express these overlay
- * Surfaces (for example, the Magnification Overlay could be implemented like the Strict-mode
- * Flash and not actually use a WindowState).
- */
- boolean isScreenOverlay() {
- return false;
+ return p.makeChildSurface(child)
+ .setParent(mSurfaceControl);
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 90e9c23..502fc127 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -58,6 +58,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -4346,27 +4347,19 @@
@Override
boolean shouldMagnify() {
if (mAttrs.type == TYPE_INPUT_METHOD ||
- mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
- return false;
- } else if (isScreenOverlay()) {
+ mAttrs.type == TYPE_INPUT_METHOD_DIALOG ||
+ mAttrs.type == TYPE_MAGNIFICATION_OVERLAY ||
+ mAttrs.type == TYPE_NAVIGATION_BAR ||
+ // It's tempting to wonder: Have we forgotten the rounded corners overlay?
+ // worry not: it's a fake TYPE_NAVIGATION_BAR_PANEL
+ mAttrs.type == TYPE_NAVIGATION_BAR_PANEL ||
+ mAttrs.type == TYPE_STATUS_BAR) {
return false;
}
return true;
}
@Override
- boolean isScreenOverlay() {
- // It's tempting to wonder: Have we forgotten the rounded corners overlay?
- // worry not: it's a fake TYPE_NAVIGATION_BAR.
- if (mAttrs.type == TYPE_MAGNIFICATION_OVERLAY ||
- mAttrs.type == TYPE_NAVIGATION_BAR ||
- mAttrs.type == TYPE_STATUS_BAR) {
- return true;
- }
- return false;
- }
-
- @Override
SurfaceSession getSession() {
if (mSession.mSurfaceSession != null) {
return mSession.mSurfaceSession;