Switched WindowState to use WindowContainer for managing children
Bug: 30060889
Change-Id: Ia451b623123210514e79f830f92f6459169911b6
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 05ce7ae..1000043 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -362,7 +362,7 @@
win.destroyOrSaveSurface();
if (win.mRemoveOnExit) {
- win.removeLocked();
+ win.remove();
}
final DisplayContent displayContent = win.getDisplayContent();
if (displayContent != null && !displayList.contains(displayContent)) {
@@ -680,10 +680,10 @@
candidate.mReplacingWindow.mSkipEnterAnimationForSeamlessReplacement = false;
}
// Since the window already timed out, remove it immediately now.
- // Use WindowState#removeLocked() instead of removeWindowLocked(), as the latter
+ // Use WindowState#remove() instead of removeWindowLocked(), as the latter
// delays removal on certain conditions, which will leave the stale window in the
// stack and marked mWillReplaceWindow=false, so the window will never be removed.
- candidate.removeLocked();
+ candidate.remove();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6a9fb58..1976088 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2418,7 +2418,7 @@
}
}
- win.removeLocked();
+ win.remove();
// Removing a visible window will effect the computed orientation
// So just update orientation if needed.
if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
@@ -2430,7 +2430,7 @@
/**
* Performs some centralized bookkeeping clean-up on the window that is being removed.
- * NOTE: Should only be called from {@link WindowState#removeLocked()}
+ * NOTE: Should only be called from {@link WindowState#remove()}
*/
void postWindowRemoveCleanupLocked(WindowState win) {
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f756ae9..21d02f8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -57,6 +57,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedList;
import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -113,6 +115,8 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
+import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
@@ -127,7 +131,7 @@
/**
* A window in the window manager.
*/
-final class WindowState implements WindowManagerPolicy.WindowState {
+class WindowState extends WindowContainer implements WindowManagerPolicy.WindowState {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
// The minimal size of a window within the usable area of the freeform stack.
@@ -160,8 +164,7 @@
// modified they will need to be locked.
final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
final DeathRecipient mDeathRecipient;
- private final WindowState mParentWindow;
- private final WindowList mChildWindows = new WindowList();
+ private boolean mIsChildWindow;
final int mBaseLayer;
final int mSubLayer;
final boolean mLayoutAttached;
@@ -511,6 +514,22 @@
*/
boolean mSeamlesslyRotated = false;
+ /**
+ * Compares to window sub-layers and returns -1 if the first is lesser than the second in terms
+ * of z-order and 1 otherwise.
+ */
+ private static final Comparator<WindowContainer> sWindowSubLayerComparator = (w1, w2) -> {
+ final int layer1 = ((WindowState)w1).mSubLayer;
+ final int layer2 = ((WindowState)w2).mSubLayer;
+ if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) {
+ // We insert the child window into the list ordered by the sub-layer.
+ // For same sub-layers, the negative one should go below others; the positive one should
+ // go above others.
+ return -1;
+ }
+ return 1;
+ };
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent, int ownerId) {
@@ -549,7 +568,7 @@
c.asBinder().linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
mDeathRecipient = null;
- mParentWindow = null;
+ mIsChildWindow = false;
mLayoutAttached = false;
mIsImWindow = false;
mIsWallpaper = false;
@@ -562,60 +581,35 @@
}
mDeathRecipient = deathRecipient;
- if ((mAttrs.type >= FIRST_SUB_WINDOW &&
- mAttrs.type <= LAST_SUB_WINDOW)) {
+ if ((mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW)) {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
- mBaseLayer = mPolicy.windowTypeToLayerLw(
- parentWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
+ mBaseLayer = mPolicy.windowTypeToLayerLw(parentWindow.mAttrs.type)
+ * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
- mParentWindow = parentWindow;
- if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mParentWindow);
+ mIsChildWindow = true;
- final WindowList childWindows = mParentWindow.mChildWindows;
- final int numChildWindows = childWindows.size();
- if (numChildWindows == 0) {
- childWindows.add(this);
- } else {
- boolean added = false;
- for (int i = 0; i < numChildWindows; i++) {
- final int childSubLayer = childWindows.get(i).mSubLayer;
- if (mSubLayer < childSubLayer
- || (mSubLayer == childSubLayer && childSubLayer < 0)) {
- // We insert the child window into the list ordered by the sub-layer. For
- // same sub-layers, the negative one should go below others; the positive
- // one should go above others.
- childWindows.add(i, this);
- added = true;
- break;
- }
- }
- if (!added) {
- childWindows.add(this);
- }
- }
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow);
+ parentWindow.addChild(this, sWindowSubLayerComparator);
mLayoutAttached = mAttrs.type !=
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
|| parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER;
- mIsFloatingLayer = mIsImWindow || mIsWallpaper;
} else {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
+ * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
mSubLayer = 0;
- mParentWindow = null;
+ mIsChildWindow = false;
mLayoutAttached = false;
mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
|| mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
- mIsFloatingLayer = mIsImWindow || mIsWallpaper;
}
+ mIsFloatingLayer = mIsImWindow || mIsWallpaper;
final WindowState appWin = getTopParentWindow();
WindowToken appToken = appWin.mToken;
@@ -1407,7 +1401,7 @@
return mHasSurface && (mContentChanged || mMovedByResize)
&& !mAnimatingExit && mService.okToDisplay()
&& (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left)
- && (!isChildWindow() || !mParentWindow.hasMoved());
+ && (!mIsChildWindow || !getParentWindow().hasMoved());
}
boolean isObscuringFullscreen(final DisplayInfo displayInfo) {
@@ -1448,19 +1442,16 @@
&& mAppToken.mTask.mStack.isAdjustedForMinimizedDock();
}
- void removeLocked() {
+ @Override
+ void remove() {
+ super.remove();
+
if (mRemoved) {
// Nothing to do.
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "WS.removeLocked: " + this + " Already removed...");
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "WS.remove: " + this + " Already removed...");
return;
}
- for (int i = mChildWindows.size() - 1; i >= 0; i--) {
- final WindowState child = mChildWindows.get(i);
- Slog.w(TAG_WM, "Force-removing child win " + child + " from container " + this);
- child.removeLocked();
- }
-
mRemoved = true;
if (mService.mInputMethodTarget == this) {
@@ -1476,10 +1467,6 @@
disposeInputChannel();
- if (isChildWindow()) {
- if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mParentWindow);
- mParentWindow.mChildWindows.remove(this);
- }
mWinAnimator.destroyDeferredSurfaceLocked();
mWinAnimator.destroySurfaceLocked();
mSession.windowRemovedLocked();
@@ -1652,7 +1639,7 @@
win.mReplacingWindow = null;
mSkipEnterAnimationForSeamlessReplacement = false;
if (win.mAnimatingExit || !animateReplacingWindow) {
- win.removeLocked();
+ win.remove();
}
}
}
@@ -2556,8 +2543,8 @@
pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
pw.print(" h="); pw.println(mLastRequestedHeight);
}
- if (isChildWindow() || mLayoutAttached) {
- pw.print(prefix); pw.print("mParentWindow="); pw.print(mParentWindow);
+ if (mIsChildWindow || mLayoutAttached) {
+ pw.print(prefix); pw.print("mParentWindow="); pw.print(getParentWindow());
pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
}
if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
@@ -2743,7 +2730,7 @@
mLastTitle = title;
mWasExiting = mAnimatingExit;
mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
- + " u" + UserHandle.getUserId(mSession.mUid)
+ + " u" + UserHandle.getUserId(mOwnerUid)
+ " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}");
}
return mStringNameCache;
@@ -2775,7 +2762,7 @@
// but SurfaceViews want to be always at a specific location so we don't fit it to the
// display.
final boolean fitToDisplay = (task == null || !nonFullscreenTask)
- || (isChildWindow() && !noLimits);
+ || (mIsChildWindow && !noLimits);
float x, y;
int w,h;
@@ -2846,16 +2833,7 @@
}
boolean isChildWindow() {
- return mParentWindow != null;
- }
-
- boolean hasChild(WindowState child) {
- for (int i = mChildWindows.size() - 1; i >= 0; --i) {
- if (mChildWindows.get(i) == child) {
- return true;
- }
- }
- return false;
+ return mIsChildWindow;
}
/**
@@ -2864,29 +2842,33 @@
WindowState getBottomChild() {
// Child windows are z-ordered based on sub-layer using {@link #sWindowSubLayerComparator}
// and the child with the lowest z-order will be at the head of the list.
- return mChildWindows.isEmpty() ? null : mChildWindows.get(0);
+ return (WindowState) mChildren.peekFirst();
}
boolean layoutInParentFrame() {
- return isChildWindow() && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
+ return mIsChildWindow
+ && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
}
/** Returns the parent window if this is a child of another window, else null. */
WindowState getParentWindow() {
- return mParentWindow;
+ // NOTE: We are not calling getParent() directly as the WindowState might be a child of a
+ // WindowContainer that isn't a WindowState.
+ return (mIsChildWindow) ? ((WindowState) super.getParent()) : null;
}
/** Returns the topmost parent window if this is a child of another window, else this. */
WindowState getTopParentWindow() {
WindowState w = this;
- while (w.isChildWindow()) {
+ while (w.mIsChildWindow) {
w = w.getParentWindow();
}
return w;
}
boolean isParentWindowHidden() {
- return (mParentWindow != null) ? mParentWindow.mHidden : false;
+ final WindowState parent = getParentWindow();
+ return (parent == null) ? false : parent.mHidden;
}
void setReplacing(boolean animate) {
@@ -2950,7 +2932,7 @@
// them at such phases, as they won't be covered by window preservation,
// and in general we expect them to return following relaunch.
boolean shouldBeReplacedWithChildren() {
- return isChildWindow() || mAttrs.type == TYPE_APPLICATION;
+ return mIsChildWindow || mAttrs.type == TYPE_APPLICATION;
}
public int getRotationAnimationHint() {
@@ -2991,8 +2973,8 @@
mHidden = false;
final DisplayContent displayContent = getDisplayContent();
- for (int i = mChildWindows.size(); i >= 0; --i) {
- final WindowState c = mChildWindows.get(i);
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowState c = (WindowState) mChildren.get(i);
if (c.mWinAnimator.mSurfaceController != null) {
c.performShowLocked();
// It hadn't been shown, which means layout not performed on it, so now we
@@ -3044,30 +3026,29 @@
windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor;
windowInfo.focused = isFocused();
- if (isChildWindow()) {
- windowInfo.parentToken = mParentWindow.mClient.asBinder();
+ if (mIsChildWindow) {
+ windowInfo.parentToken = getParentWindow().mClient.asBinder();
}
- final int childCount = mChildWindows.size();
+ final int childCount = mChildren.size();
if (childCount > 0) {
if (windowInfo.childTokens == null) {
- windowInfo.childTokens = new ArrayList<>();
+ windowInfo.childTokens = new ArrayList(childCount);
}
for (int j = 0; j < childCount; j++) {
- final WindowState child = mChildWindows.get(j);
+ final WindowState child = (WindowState) mChildren.get(j);
windowInfo.childTokens.add(child.mClient.asBinder());
}
}
-
return windowInfo;
}
void adjustAnimLayer(int adj) {
mWinAnimator.mAnimLayer = mLayer + adj;
if (DEBUG_LAYERS) Slog.v(TAG_WM, "win=" + this + " anim layer: " + mWinAnimator.mAnimLayer);
- for (int i = mChildWindows.size() - 1; i >= 0; i--) {
- final WindowState child = mChildWindows.get(i);
- child.adjustAnimLayer(adj);
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState childWindow = (WindowState) mChildren.get(i);
+ childWindow.adjustAnimLayer(adj);
}
}
@@ -3078,10 +3059,10 @@
final WindowList windows = getWindowList();
// Adding child windows relies on child windows being ordered by mSubLayer using
// {@link #sWindowSubLayerComparator}.
- final int childCount = mChildWindows.size();
+ final int childCount = mChildren.size();
boolean winAdded = false;
for (int j = 0; j < childCount; j++) {
- WindowState child = mChildWindows.get(j);
+ final WindowState child = (WindowState) mChildren.get(j);
if (!winAdded && child.mSubLayer >= 0) {
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
"Re-adding child window at " + index + ": " + child);
@@ -3116,10 +3097,10 @@
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
windows.remove(wpos);
mService.mWindowsChanged = true;
- int childCount = mChildWindows.size();
+ int childCount = mChildren.size();
while (childCount > 0) {
childCount--;
- final WindowState cw = mChildWindows.get(childCount);
+ final WindowState cw = (WindowState) mChildren.get(childCount);
int cpos = windows.indexOf(cw);
if (cpos >= 0) {
if (cpos < interestingPos) interestingPos--;
@@ -3136,11 +3117,12 @@
+ ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
+ " windowAnimating=" + mWinAnimator.isWindowAnimationSet());
- if (!mChildWindows.isEmpty()) {
+ if (!mChildren.isEmpty()) {
// Copying to a different list as multiple children can be removed.
- final WindowList childWindows = new WindowList(mChildWindows);
+ // TODO: Not sure if we really need to copy this into a different list.
+ final LinkedList childWindows = new LinkedList(mChildren);
for (int i = childWindows.size() - 1; i >= 0; i--) {
- childWindows.get(i).onExitAnimationDone();
+ ((WindowState)childWindows.get(i)).onExitAnimationDone();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 4a2325c..b8dec49 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -215,7 +215,7 @@
while (!mService.mForceRemoves.isEmpty()) {
final WindowState ws = mService.mForceRemoves.remove(0);
Slog.i(TAG, "Force removing: " + ws);
- ws.removeLocked();
+ ws.remove();
}
Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
Object tmp = new Object();
@@ -545,7 +545,7 @@
DisplayContentList displayList = new DisplayContentList();
for (i = 0; i < N; i++) {
final WindowState w = mService.mPendingRemoveTmp[i];
- w.removeLocked();
+ w.remove();
final DisplayContent displayContent = w.getDisplayContent();
if (displayContent != null && !displayList.contains(displayContent)) {
displayList.add(displayContent);