WM: Refactor DisplayContent in preparation for DisplayArea (1/n)
To allow for DisplayArea, the following needs to be hierarchized first: - IME window traversal & layer assignment - Splitscreen layer assignment - Rounded corner layer creation and assignment. While we're here, we'll also clean up the display re-positioning, which will interfere with DisplayArea repositioning. Bug: 147406652 Test: atest WmTests Change-Id: I53b816ec0450070847d582ce12fc50b40d7fceef
This commit is contained in:
@@ -70,7 +70,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFI
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
|
||||
@@ -304,8 +303,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
|
||||
// window containers together and move them in-sync if/when needed. We use a subclass of
|
||||
// WindowContainer which is omitted from screen magnification, as the IME is never magnified.
|
||||
private final NonAppWindowContainers mImeWindowsContainers =
|
||||
new NonAppWindowContainers("mImeWindowsContainers", mWmService);
|
||||
// TODO(display-area): is "no magnification" in the comment still true?
|
||||
private final ImeContainer mImeWindowsContainers = new ImeContainer(mWmService);
|
||||
|
||||
private WindowState mTmpWindow;
|
||||
private WindowState mTmpWindow2;
|
||||
@@ -1995,6 +1994,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
return mTaskStackContainers.getVisibleTasks();
|
||||
}
|
||||
|
||||
SurfaceControl getSplitScreenDividerAnchor() {
|
||||
return mTaskStackContainers.getSplitScreenDividerAnchor();
|
||||
}
|
||||
|
||||
void onStackWindowingModeChanged(ActivityStack stack) {
|
||||
mTaskStackContainers.onStackWindowingModeChanged(stack);
|
||||
}
|
||||
@@ -2081,7 +2084,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
|
||||
boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
|
||||
return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
|
||||
return mImeWindowsContainers.forAllWindowForce(callback, traverseTopToBottom);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2339,11 +2342,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
throw new UnsupportedOperationException("See DisplayChildWindowContainer");
|
||||
}
|
||||
|
||||
void positionDisplayAt(int position, boolean includingParents) {
|
||||
getParent().positionChildAt(position, this, includingParents);
|
||||
}
|
||||
|
||||
@Override
|
||||
void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) {
|
||||
// Children of the display are statically ordered, so the real intention here is to perform
|
||||
// the operation on the display and not the static direct children.
|
||||
getParent().positionChildAt(position, this, includingParents);
|
||||
positionDisplayAt(position, includingParents);
|
||||
}
|
||||
|
||||
void positionStackAt(int position, ActivityStack child, boolean includingParents) {
|
||||
@@ -4289,8 +4296,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
@Override
|
||||
void positionChildAt(int position, ActivityStack child, boolean includingParents) {
|
||||
if (child.getWindowConfiguration().isAlwaysOnTop()
|
||||
&& position != POSITION_TOP && position != mChildren.size()) {
|
||||
final boolean moveToTop = (position == POSITION_TOP || position == getChildCount());
|
||||
final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0);
|
||||
if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
|
||||
// This stack is always-on-top, override the default behavior.
|
||||
Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
|
||||
|
||||
@@ -4306,18 +4314,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
includingParents = false;
|
||||
}
|
||||
final int targetPosition = findPositionForStack(position, child, false /* adding */);
|
||||
super.positionChildAt(targetPosition, child, includingParents);
|
||||
super.positionChildAt(targetPosition, child, false /* includingParents */);
|
||||
|
||||
if (includingParents) {
|
||||
// We still want to move the display of this stack container to top because even the
|
||||
// target position is adjusted to non-top, the intention of the condition is to have
|
||||
// higher z-order to gain focus (e.g. moving a task of a fullscreen stack to front
|
||||
// in a non-top display which is using picture-in-picture mode).
|
||||
final int topChildPosition = getChildCount() - 1;
|
||||
if (targetPosition < topChildPosition && position >= topChildPosition) {
|
||||
getParent().positionChildAt(POSITION_TOP, this /* child */,
|
||||
true /* includingParents */);
|
||||
}
|
||||
if (includingParents && (moveToTop || moveToBottom)) {
|
||||
// The DisplayContent children do not re-order, but we still want to move the
|
||||
// display of this stack container because the intention of positioning is to have
|
||||
// higher z-order to gain focus.
|
||||
positionDisplayAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
|
||||
true /* includingParents */);
|
||||
}
|
||||
|
||||
setLayoutNeeded();
|
||||
@@ -4636,39 +4640,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
super(name, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
|
||||
final SurfaceControl.Builder builder = super.makeChildSurface(child);
|
||||
if (child instanceof WindowToken && ((WindowToken) child).mRoundedCornerOverlay) {
|
||||
// To draw above the ColorFade layer during the screen off transition, the
|
||||
// rounded corner overlays need to be at the root of the surface hierarchy.
|
||||
// TODO: move the ColorLayer into the display overlay layer such that this is not
|
||||
// necessary anymore.
|
||||
builder.setParent(null);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
void assignChildLayers(SurfaceControl.Transaction t) {
|
||||
assignChildLayers(t, null /* imeContainer */);
|
||||
}
|
||||
|
||||
void assignChildLayers(SurfaceControl.Transaction t, WindowContainer imeContainer) {
|
||||
boolean needAssignIme = imeContainer != null
|
||||
&& imeContainer.getSurfaceControl() != null;
|
||||
boolean needAssignIme = mImeWindowsContainers.getSurfaceControl() != null;
|
||||
for (int j = 0; j < mChildren.size(); ++j) {
|
||||
final WindowToken wt = mChildren.get(j);
|
||||
|
||||
// See {@link mSplitScreenDividerAnchor}
|
||||
if (wt.windowType == TYPE_DOCK_DIVIDER) {
|
||||
wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1);
|
||||
continue;
|
||||
}
|
||||
if (wt.mRoundedCornerOverlay) {
|
||||
wt.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
|
||||
continue;
|
||||
}
|
||||
wt.assignLayer(t, j);
|
||||
wt.assignChildLayers(t);
|
||||
|
||||
@@ -4677,13 +4654,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
if (needAssignIme && layer >= mWmService.mPolicy.getWindowLayerFromTypeLw(
|
||||
TYPE_INPUT_METHOD_DIALOG, true)) {
|
||||
imeContainer.assignRelativeLayer(t, wt.getSurfaceControl(), -1);
|
||||
mImeWindowsContainers.assignRelativeLayer(t, wt.getSurfaceControl(), -1);
|
||||
needAssignIme = false;
|
||||
}
|
||||
}
|
||||
if (needAssignIme) {
|
||||
imeContainer.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4697,6 +4671,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
@Override
|
||||
void assignChildLayers(SurfaceControl.Transaction t) {
|
||||
mImeWindowsContainers.setNeedsLayer();
|
||||
mBelowAppWindowsContainers.assignLayer(t, 0);
|
||||
mTaskStackContainers.assignLayer(t, 1);
|
||||
mAboveAppWindowsContainers.assignLayer(t, 2);
|
||||
@@ -4732,15 +4707,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
// 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,
|
||||
needAssignIme ? mImeWindowsContainers : null);
|
||||
mAboveAppWindowsContainers.assignChildLayers(t);
|
||||
mImeWindowsContainers.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE);
|
||||
mImeWindowsContainers.assignChildLayers(t);
|
||||
}
|
||||
|
||||
@@ -4756,47 +4730,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
addChild(mImeWindowsContainers, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* In split-screen mode we process the IME containers above the docked divider
|
||||
* rather than directly above their target.
|
||||
*/
|
||||
private boolean skipTraverseChild(WindowContainer child) {
|
||||
return child == mImeWindowsContainers && mInputMethodTarget != null
|
||||
&& !hasSplitScreenPrimaryStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean forAllWindows(ToBooleanFunction<WindowState> callback,
|
||||
boolean traverseTopToBottom) {
|
||||
// Special handling so we can process IME windows with #forAllImeWindows above their IME
|
||||
// target, or here in order if there isn't an IME target.
|
||||
if (traverseTopToBottom) {
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer child = mChildren.get(i);
|
||||
if (skipTraverseChild(child)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child.forAllWindows(callback, traverseTopToBottom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final int count = mChildren.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final WindowContainer child = mChildren.get(i);
|
||||
if (skipTraverseChild(child)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child.forAllWindows(callback, traverseTopToBottom)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void positionChildAt(int position, WindowContainer child, boolean includingParents) {
|
||||
// Children of the WindowContainers are statically ordered, so the real intention here
|
||||
@@ -4910,6 +4843,68 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Container for IME windows.
|
||||
*
|
||||
* This has some special behaviors:
|
||||
* - layers assignment is ignored except if setNeedsLayer() has been called before (and no
|
||||
* layer has been assigned since), to facilitate assigning the layer from the IME target, or
|
||||
* fall back if there is no target.
|
||||
* - the container doesn't always participate in window traversal, according to
|
||||
* {@link #skipImeWindowsDuringTraversal()}
|
||||
*/
|
||||
private class ImeContainer extends NonAppWindowContainers {
|
||||
boolean mNeedsLayer = false;
|
||||
|
||||
ImeContainer(WindowManagerService wms) {
|
||||
super("ImeContainer", wms);
|
||||
}
|
||||
|
||||
public void setNeedsLayer() {
|
||||
mNeedsLayer = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean forAllWindows(ToBooleanFunction<WindowState> callback,
|
||||
boolean traverseTopToBottom) {
|
||||
final DisplayContent dc = mDisplayContent;
|
||||
if (skipImeWindowsDuringTraversal(dc)) {
|
||||
return false;
|
||||
}
|
||||
return super.forAllWindows(callback, traverseTopToBottom);
|
||||
}
|
||||
|
||||
private boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
|
||||
// We skip IME windows so they're processed just above their target, except
|
||||
// in split-screen mode where we process the IME containers above the docked divider.
|
||||
return dc.mInputMethodTarget != null && !dc.hasSplitScreenPrimaryStack();
|
||||
}
|
||||
|
||||
/** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */
|
||||
boolean forAllWindowForce(ToBooleanFunction<WindowState> callback,
|
||||
boolean traverseTopToBottom) {
|
||||
return super.forAllWindows(callback, traverseTopToBottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
void assignLayer(Transaction t, int layer) {
|
||||
if (!mNeedsLayer) {
|
||||
return;
|
||||
}
|
||||
super.assignLayer(t, layer);
|
||||
mNeedsLayer = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
|
||||
if (!mNeedsLayer) {
|
||||
return;
|
||||
}
|
||||
super.assignRelativeLayer(t, relativeTo, layer);
|
||||
mNeedsLayer = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
SurfaceSession getSession() {
|
||||
return mSession;
|
||||
@@ -5013,6 +5008,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
* with {@link WindowState#assignLayer}
|
||||
*/
|
||||
void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) {
|
||||
mImeWindowsContainers.setNeedsLayer();
|
||||
child.assignRelativeLayer(t, mImeWindowsContainers.getSurfaceControl(), 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2764,7 +2764,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
synchronized (mGlobalLock) {
|
||||
final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
|
||||
if (displayContent != null && mRoot.getTopChild() != displayContent) {
|
||||
mRoot.positionChildAt(WindowContainer.POSITION_TOP, displayContent,
|
||||
displayContent.positionDisplayAt(WindowContainer.POSITION_TOP,
|
||||
true /* includingParents */);
|
||||
}
|
||||
}
|
||||
@@ -7647,7 +7647,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
final DisplayContent displayContent = touchedWindow.getDisplayContent();
|
||||
if (!displayContent.isOnTop()) {
|
||||
displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent,
|
||||
displayContent.positionDisplayAt(WindowContainer.POSITION_TOP,
|
||||
true /* includingParents */);
|
||||
}
|
||||
handleTaskFocusChange(touchedWindow.getTask());
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
|
||||
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||
@@ -38,7 +39,9 @@ import android.annotation.CallSuper;
|
||||
import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.server.policy.WindowManagerPolicy;
|
||||
import com.android.server.protolog.common.ProtoLog;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -256,6 +259,27 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
super.onDisplayChanged(dc);
|
||||
}
|
||||
|
||||
@Override
|
||||
void assignLayer(SurfaceControl.Transaction t, int layer) {
|
||||
if (windowType == TYPE_DOCK_DIVIDER) {
|
||||
// See {@link DisplayContent#mSplitScreenDividerAnchor}
|
||||
super.assignRelativeLayer(t, mDisplayContent.getSplitScreenDividerAnchor(), 1);
|
||||
} else if (mRoundedCornerOverlay) {
|
||||
super.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
|
||||
} else {
|
||||
super.assignLayer(t, layer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
SurfaceControl.Builder makeSurface() {
|
||||
final SurfaceControl.Builder builder = super.makeSurface();
|
||||
if (mRoundedCornerOverlay) {
|
||||
builder.setParent(null);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void dumpDebug(ProtoOutputStream proto, long fieldId,
|
||||
@@ -315,4 +339,8 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
mOwnerCanManageAppTokens);
|
||||
return mOwnerCanManageAppTokens && (layer > navLayer);
|
||||
}
|
||||
|
||||
int getWindowLayerFromType() {
|
||||
return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user