From a6cc361e34337c7fe293a56713910faf0f2f302c Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Thu, 4 Aug 2016 07:25:33 -0700 Subject: [PATCH] Add child windows to their parent WindowToken Previously child windows were contained in their own WindowToken and also added to the parent window AppWindowToken.allAppsWindow. This complicated the token organization within WM as it was sometimes confusing which list to use WindowTokens.windows or appAppsWindow which led to many bugs fixed and still existing. I can't think of a good reason why the child windows just can't be tracked with the parent token so we will do that and fix whatever bug may come. This paves the way to consolidate WT.windows and AWT.appAppsWindow list since they will contain the same entries now and also fits in with the hierarchy model we will be using with WindowContainers. Also - Removed WindowState.mRootToken since a window and its children will now be in the same WindowToken. - Fixed NPE in WindowState.getTopParentWindow() - Temp. workaround to not re-add child windows in WT.reAddAppWindows since WindowState.reAddWindowLocked() will re-add any children of the parent window we are adding. Workaround can be removed when the class is switched to use WindowContainer. Bug: 30060889 Change-Id: I604ba4cce9ff8df4e81353cb648d6f54aa27084f --- .../com/android/server/wm/AppWindowToken.java | 1 - .../com/android/server/wm/WindowAnimator.java | 2 +- .../server/wm/WindowManagerService.java | 71 ++++++++++--------- .../com/android/server/wm/WindowState.java | 24 +++---- .../server/wm/WindowSurfacePlacer.java | 4 +- .../com/android/server/wm/WindowToken.java | 10 +++ 6 files changed, 60 insertions(+), 52 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 47f435f0c7cad..7004e355179a1 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -1260,7 +1260,6 @@ class AppWindowToken extends WindowToken { fromToken.startingWindow = null; fromToken.startingMoved = true; tStartingWindow.mToken = this; - tStartingWindow.mRootToken = this; tStartingWindow.mAppToken = this; if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 6e7313cb1f416..2a1e72074366e 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -354,7 +354,7 @@ public class WindowAnimator { + " destroying=" + win.mDestroying + " parentHidden=" + win.isParentWindowHidden() + " vis=" + win.mViewVisibility - + " hidden=" + win.mRootToken.hidden + + " hidden=" + win.mToken.hidden + " anim=" + win.mWinAnimator.mAnimation); } else if (canBeForceHidden) { if (shouldBeForceHidden) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 261e7b73d9fa9..f41693aa9b131 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1461,7 +1461,7 @@ public class WindowManagerService extends IWindowManager.Stub } boolean reportNewConfig = false; - WindowState attachedWindow = null; + WindowState parentWindow = null; long origId; final int type = attrs.type; @@ -1488,14 +1488,14 @@ public class WindowManagerService extends IWindowManager.Stub } if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { - attachedWindow = windowForClientLocked(null, attrs.token, false); - if (attachedWindow == null) { + parentWindow = windowForClientLocked(null, attrs.token, false); + if (parentWindow == null) { Slog.w(TAG_WM, "Attempted to add window with token that is not a window: " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; } - if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW - && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { + if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW + && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) { Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; @@ -1507,46 +1507,52 @@ public class WindowManagerService extends IWindowManager.Stub return WindowManagerGlobal.ADD_PERMISSION_DENIED; } - WindowToken token = mTokenMap.get(attrs.token); AppWindowToken atoken = null; + final boolean hasParent = parentWindow != null; + // Use existing parent window token for child windows since they go in the same token + // as there parent window so we can apply the same policy on them. + WindowToken token = mTokenMap.get(hasParent ? parentWindow.mAttrs.token : attrs.token); + // If this is a child window, we want to apply the same type checking rules as the + // parent window type. + final int rootType = hasParent ? parentWindow.mAttrs.type : type; if (token == null) { - if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { + if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) { Slog.w(TAG_WM, "Attempted to add application window with unknown token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - if (type == TYPE_INPUT_METHOD) { + if (rootType == TYPE_INPUT_METHOD) { Slog.w(TAG_WM, "Attempted to add input method window with unknown token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - if (type == TYPE_VOICE_INTERACTION) { + if (rootType == TYPE_VOICE_INTERACTION) { Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - if (type == TYPE_WALLPAPER) { + if (rootType == TYPE_WALLPAPER) { Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - if (type == TYPE_DREAM) { + if (rootType == TYPE_DREAM) { Slog.w(TAG_WM, "Attempted to add Dream window with unknown token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - if (type == TYPE_QS_DIALOG) { + if (rootType == TYPE_QS_DIALOG) { Slog.w(TAG_WM, "Attempted to add QS dialog window with unknown token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - if (type == TYPE_ACCESSIBILITY_OVERLAY) { + if (rootType == TYPE_ACCESSIBILITY_OVERLAY) { Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with unknown token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } token = new WindowToken(this, attrs.token, -1, false); - } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { + } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) { atoken = token.asAppWindowToken(); if (atoken == null) { Slog.w(TAG_WM, "Attempted to add window with non-application token " @@ -1557,57 +1563,57 @@ public class WindowManagerService extends IWindowManager.Stub + token + ". Aborting."); return WindowManagerGlobal.ADD_APP_EXITING; } - if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { + if (rootType == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { // No need for this guy! if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v( TAG_WM, "**** NO NEED TO START: " + attrs.getTitle()); return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; } - } else if (type == TYPE_INPUT_METHOD) { + } else if (rootType == TYPE_INPUT_METHOD) { if (token.windowType != TYPE_INPUT_METHOD) { Slog.w(TAG_WM, "Attempted to add input method window with bad token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - } else if (type == TYPE_VOICE_INTERACTION) { + } else if (rootType == TYPE_VOICE_INTERACTION) { if (token.windowType != TYPE_VOICE_INTERACTION) { Slog.w(TAG_WM, "Attempted to add voice interaction window with bad token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - } else if (type == TYPE_WALLPAPER) { + } else if (rootType == TYPE_WALLPAPER) { if (token.windowType != TYPE_WALLPAPER) { Slog.w(TAG_WM, "Attempted to add wallpaper window with bad token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - } else if (type == TYPE_DREAM) { + } else if (rootType == TYPE_DREAM) { if (token.windowType != TYPE_DREAM) { Slog.w(TAG_WM, "Attempted to add Dream window with bad token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - } else if (type == TYPE_ACCESSIBILITY_OVERLAY) { + } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) { if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) { Slog.w(TAG_WM, "Attempted to add Accessibility overlay window with bad token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } - } else if (type == TYPE_QS_DIALOG) { + } else if (rootType == TYPE_QS_DIALOG) { if (token.windowType != TYPE_QS_DIALOG) { Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token " + attrs.token + ". Aborting."); return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } } else if (token.asAppWindowToken() != null) { - Slog.w(TAG_WM, "Non-null appWindowToken for system window of type=" + type); + Slog.w(TAG_WM, "Non-null appWindowToken for system window of rootType=" + rootType); // It is not valid to use an app token with other system types; we will // instead make a new token for it (as if null had been passed in for the token). attrs.token = null; token = new WindowToken(this, null, -1, false); } - WindowState win = new WindowState(this, session, client, token, attachedWindow, + WindowState win = new WindowState(this, session, client, token, parentWindow, appOp[0], seq, attrs, viewVisibility, displayContent, session.mUid); if (win.mDeathRecipient == null) { // Client has apparently died, so there is no reason to @@ -8176,16 +8182,13 @@ public class WindowManagerService extends IWindowManager.Stub // Internals // ------------------------------------------------------------- - final WindowState windowForClientLocked(Session session, IWindow client, - boolean throwOnError) { + final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) { return windowForClientLocked(session, client.asBinder(), throwOnError); } - final WindowState windowForClientLocked(Session session, IBinder client, - boolean throwOnError) { + final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) { WindowState win = mWindowMap.get(client); - if (localLOGV) Slog.v( - TAG_WM, "Looking up client " + client + ": " + win); + if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win); if (win == null) { RuntimeException ex = new IllegalArgumentException( "Requested window " + client + " does not exist"); @@ -8245,15 +8248,13 @@ public class WindowManagerService extends IWindowManager.Stub i++; } - // Keep whatever windows were below the app windows still below, - // by skipping them. + // Keep whatever windows were below the app windows still below, by skipping them. lastBelow++; i = lastBelow; - // First add all of the exiting app tokens... these are no longer - // in the main app list, but still have windows shown. We put them - // in the back because now that the animation is over we no longer - // will care about them. + // First add all of the exiting app tokens... these are no longer in the main app list, + // but still have windows shown. We put them in the back because now that the animation is + // over we no longer will care about them. final ArrayList stacks = displayContent.getStacks(); final int numStacks = stacks.size(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d9836a840e8f4..67a7a09b7efe6 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -165,7 +165,7 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS final int mOwnerUid; final IWindowId mWindowId; WindowToken mToken; - WindowToken mRootToken; + // The same object as mToken if this is an app window and null for non-app windows. AppWindowToken mAppToken; // mAttrs.flags is tested in animation without being locked. If the bits tested are ever @@ -554,6 +554,7 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS mClient = c; mAppOp = appOp; mToken = token; + mAppToken = mToken.asAppWindowToken(); mOwnerUid = ownerId; mWindowId = new IWindowId.Stub() { @Override @@ -627,8 +628,6 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS } mIsFloatingLayer = mIsImWindow || mIsWallpaper; - mRootToken = getTopParentWindow().mToken; - mAppToken = mRootToken.asAppWindowToken(); if (mAppToken != null) { final DisplayContent appDisplay = getDisplayContent(); mNotOnAppsDisplay = displayContent != appDisplay; @@ -1192,14 +1191,14 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS */ @Override public boolean isVisibleOrBehindKeyguardLw() { - if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { + if (mToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { return false; } final AppWindowToken atoken = mAppToken; final boolean animating = atoken != null && atoken.mAppAnimator.animation != null; return mHasSurface && !mDestroying && !mAnimatingExit && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested) - && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mRootToken.hidden) + && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.hidden) || mWinAnimator.mAnimation != null || animating); } @@ -1217,7 +1216,7 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS * not the pending requested hidden state. */ boolean isVisibleNow() { - return (!mRootToken.hidden || mAttrs.type == TYPE_APPLICATION_STARTING) + return (!mToken.hidden || mAttrs.type == TYPE_APPLICATION_STARTING) && isVisibleUnchecked(); } @@ -1299,11 +1298,11 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS * of a transition that has not yet been started. */ boolean isReadyForDisplay() { - if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { + if (mToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { return false; } return mHasSurface && mPolicyVisibility && !mDestroying - && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mRootToken.hidden) + && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.hidden) || mWinAnimator.mAnimation != null || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null))); } @@ -1313,7 +1312,7 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS * to the keyguard. */ boolean isReadyForDisplayIgnoringKeyguard() { - if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { + if (mToken.waitingToShow && mService.mAppTransition.isTransitionSet()) { return false; } final AppWindowToken atoken = mAppToken; @@ -1323,7 +1322,7 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS return false; } return mHasSurface && !mDestroying - && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mRootToken.hidden) + && ((!isParentWindowHidden() && mViewVisibility == View.VISIBLE && !mToken.hidden) || mWinAnimator.mAnimation != null || ((atoken != null) && (atoken.mAppAnimator.animation != null) && !mWinAnimator.isDummyAnimation())); @@ -1357,7 +1356,7 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS final AppWindowToken atoken = mAppToken; return mViewVisibility == View.GONE || !mRelayoutCalled - || (atoken == null && mRootToken.hidden) + || (atoken == null && mToken.hidden) || (atoken != null && atoken.hiddenRequested) || isParentWindowHidden() || (mAnimatingExit && !isAnimatingLw()) @@ -2728,7 +2727,6 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS } if (dumpAll) { pw.print(prefix); pw.print("mToken="); pw.println(mToken); - pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); if (mAppToken != null) { pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()="); @@ -3020,7 +3018,7 @@ class WindowState extends WindowContainer implements WindowManagerPolicy.WindowS /** Returns the topmost parent window if this is a child of another window, else this. */ WindowState getTopParentWindow() { WindowState w = this; - while (w.mIsChildWindow) { + while (w != null && w.mIsChildWindow) { w = w.getParentWindow(); } return w; diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 25709c5160d1a..c26c07804e53c 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -956,13 +956,13 @@ class WindowSurfacePlacer { if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + win.mViewVisibility + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" - + win.mRootToken.hidden + " hiddenRequested=" + + win.mToken.hidden + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) + " parentHidden=" + win.isParentWindowHidden()); else Slog.v(TAG, " VIS: mViewVisibility=" + win.mViewVisibility + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" - + win.mRootToken.hidden + " hiddenRequested=" + + win.mToken.hidden + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested) + " parentHidden=" + win.isParentWindowHidden()); } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 9f019acc31d8b..f56a0f1efc73e 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -451,6 +451,16 @@ class WindowToken { final int count = windows.size(); for (int i = 0; i < count; i++) { final WindowState win = windows.get(i); + if (win.isChildWindow()) { + // The WindowState.reAddWindowLocked below already takes care of re-adding the + // child windows for any parent window in this token. This is a side effect of + // ensuring child windows are in the same WindowToken as their parent window. + // + // TODO: Can be removed once WindowToken no longer contains child windows. i.e it is + // using WindowContainer which uses the hierarchy to access child windows through + // their parent window. + continue; + } final DisplayContent winDisplayContent = win.getDisplayContent(); if (winDisplayContent == displayContent || winDisplayContent == null) { win.mDisplayContent = displayContent;