diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 97f65ad821676..d6954a5ed2704 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -134,10 +134,11 @@ public class WindowAnimator { } private void updateWindowsAppsAndRotationAnimationsLocked() { + final ArrayList appTokens = mService.mAnimatingAppTokens; int i; - final int NAT = mService.mAppTokens.size(); + final int NAT = appTokens.size(); for (i=0; i appTokens = mService.mAnimatingAppTokens; + final int NT = appTokens.size(); for (int i=0; i 0 && wtoken.numDrawnWindows >= numInteresting) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index fda33522dfb78..d9e0ec6976d00 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -351,12 +351,19 @@ public class WindowManagerService extends IWindowManager.Stub final ArrayList mExitingTokens = new ArrayList(); /** - * Z-ordered (bottom-most first) list of all application tokens, for - * controlling the ordering of windows in different applications. This - * contains AppWindowToken objects. + * List controlling the ordering of windows in different applications which must + * be kept in sync with ActivityManager. */ final ArrayList mAppTokens = new ArrayList(); + /** + * AppWindowTokens in the Z order they were in at the start of an animation. Between + * animations this list is maintained in the exact order of mAppTokens. If tokens + * are added to mAppTokens during an animation an attempt is made to insert them at the same + * logical location in this list. Note that this list is always in sync with mWindows. + */ + ArrayList mAnimatingAppTokens = new ArrayList(); + /** * Application tokens that are in the process of exiting, but still * on screen for animations. @@ -529,8 +536,6 @@ public class WindowManagerService extends IWindowManager.Stub boolean mSkipAppTransitionAnimation = false; final ArrayList mOpeningApps = new ArrayList(); final ArrayList mClosingApps = new ArrayList(); - final ArrayList mToTopApps = new ArrayList(); - final ArrayList mToBottomApps = new ArrayList(); Display mDisplay; @@ -1010,10 +1015,10 @@ public class WindowManagerService extends IWindowManager.Stub + client.asBinder() + " (token=" + token + ")"); // Figure out where the window should go, based on the // order of applications. - final int NA = mAppTokens.size(); + final int NA = mAnimatingAppTokens.size(); WindowState pos = null; for (i=NA-1; i>=0; i--) { - AppWindowToken t = mAppTokens.get(i); + AppWindowToken t = mAnimatingAppTokens.get(i); if (t == token) { i--; break; @@ -1046,7 +1051,7 @@ public class WindowManagerService extends IWindowManager.Stub // Continue looking down until we find the first // token that has windows. while (i >= 0) { - AppWindowToken t = mAppTokens.get(i); + AppWindowToken t = mAnimatingAppTokens.get(i); final int NW = t.windows.size(); if (NW > 0) { pos = t.windows.get(NW-1); @@ -1167,6 +1172,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + /** TODO(cmautner): Is this the same as {@link WindowState#canReceiveKeys()} */ static boolean canBeImeTarget(WindowState w) { final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); @@ -1875,7 +1881,7 @@ public class WindowManagerService extends IWindowManager.Stub } wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; - if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win " + if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "adjustWallpaper win " + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); // First, if this window is at the current index, then all @@ -1929,7 +1935,7 @@ public class WindowManagerService extends IWindowManager.Stub curWallpaperIndex--; WindowState wallpaper = token.windows.get(curWallpaperIndex); wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; - if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win " + if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); } } @@ -3487,6 +3493,25 @@ public class WindowManagerService extends IWindowManager.Stub Binder.restoreCallingIdentity(origId); } + /** + * Find the location to insert a new AppWindowToken into the window-ordered app token list. + * Note that mAppTokens.size() == mAnimatingAppTokens.size() + 1. + * @param addPos The location the token was inserted into in mAppTokens. + * @param wtoken The token to insert. + */ + private void addAppTokenToAnimating(final int addPos, final AppWindowToken wtoken) { + if (addPos == 0 || addPos == mAnimatingAppTokens.size()) { + // It was inserted into the beginning or end of mAppTokens. Honor that. + mAnimatingAppTokens.add(addPos, wtoken); + return; + } + // Find the item immediately above the mAppTokens insertion point and put the token + // immediately below that one in mAnimatingAppTokens. + final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1); + mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), wtoken); + } + + @Override public void addAppToken(int addPos, IApplicationToken token, int groupId, int requestedOrientation, boolean fullscreen) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, @@ -3521,6 +3546,7 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.requestedOrientation = requestedOrientation; if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + wtoken); mAppTokens.add(addPos, wtoken); + addAppTokenToAnimating(addPos, wtoken); mTokenMap.put(token.asBinder(), wtoken); // Application tokens start out hidden. @@ -3838,7 +3864,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_APP_TRANSITIONS) Slog.v( TAG, "Prepare app transition: transit=" + transit + " mNextAppTransition=" + mNextAppTransition - + "\nCallers=" + Debug.getCallers(3)); + + " Callers=" + Debug.getCallers(3)); if (okToDisplay()) { if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) { @@ -4470,6 +4496,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " + wtoken); mAppTokens.remove(wtoken); + mAnimatingAppTokens.remove(wtoken); wtoken.removed = true; if (wtoken.startingData != null) { startingToken = wtoken; @@ -4501,11 +4528,13 @@ public class WindowManagerService extends IWindowManager.Stub private boolean tmpRemoveAppWindowsLocked(WindowToken token) { final int NW = token.windows.size(); + if (NW > 0) { + mWindowsChanged = true; + } for (int i=0; i 0) { j--; @@ -4524,6 +4553,12 @@ public class WindowManagerService extends IWindowManager.Stub } } + void dumpAnimatingAppTokensLocked() { + for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { + Slog.v(TAG, " #" + i + ": " + mAnimatingAppTokens.get(i).token); + } + } + void dumpWindowsLocked() { for (int i=mWindows.size()-1; i>=0; i--) { Slog.v(TAG, " #" + i + ": " + mWindows.get(i)); @@ -4533,7 +4568,7 @@ public class WindowManagerService extends IWindowManager.Stub private int findWindowOffsetLocked(int tokenPos) { final int NW = mWindows.size(); - if (tokenPos >= mAppTokens.size()) { + if (tokenPos >= mAnimatingAppTokens.size()) { int i = NW; while (i > 0) { i--; @@ -4547,7 +4582,7 @@ public class WindowManagerService extends IWindowManager.Stub while (tokenPos > 0) { // Find the first app token below the new position that has // a window displayed. - final AppWindowToken wtoken = mAppTokens.get(tokenPos-1); + final AppWindowToken wtoken = mAnimatingAppTokens.get(tokenPos-1); if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ " + tokenPos + " -- " + wtoken.token); if (wtoken.sendingToBottom) { @@ -4635,9 +4670,16 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:"); if (DEBUG_REORDER) dumpAppTokensLocked(); final AppWindowToken wtoken = findAppWindowToken(token); + final int oldIndex = mAppTokens.indexOf(wtoken); if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG, "Start moving token " + wtoken + " initially at " - + mAppTokens.indexOf(wtoken)); + + oldIndex); + if (oldIndex > index && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET + && !mAppTransitionRunning) { + // animation towards back has not started, copy old list for duration of animation. + mAnimatingAppTokens.clear(); + mAnimatingAppTokens.addAll(mAppTokens); + } if (wtoken == null || !mAppTokens.remove(wtoken)) { Slog.w(TAG, "Attempting to reorder token that doesn't exist: " + token + " (" + wtoken + ")"); @@ -4647,24 +4689,30 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":"); else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index); if (DEBUG_REORDER) dumpAppTokensLocked(); + if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET && !mAppTransitionRunning) { + // Not animating, bring animating app list in line with mAppTokens. + mAnimatingAppTokens.clear(); + mAnimatingAppTokens.addAll(mAppTokens); - final long origId = Binder.clearCallingIdentity(); - if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":"); - if (DEBUG_REORDER) dumpWindowsLocked(); - if (tmpRemoveAppWindowsLocked(wtoken)) { - if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:"); + // Bring window ordering, window focus and input window in line with new app token + final long origId = Binder.clearCallingIdentity(); + if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":"); if (DEBUG_REORDER) dumpWindowsLocked(); - reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken); - if (DEBUG_REORDER) Slog.v(TAG, "Final window list:"); - if (DEBUG_REORDER) dumpWindowsLocked(); - updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, - false /*updateInputWindows*/); - mLayoutNeeded = true; - mInputMonitor.setUpdateInputWindowsNeededLw(); - performLayoutAndPlaceSurfacesLocked(); - mInputMonitor.updateInputWindowsLw(false /*force*/); + if (tmpRemoveAppWindowsLocked(wtoken)) { + if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:"); + if (DEBUG_REORDER) dumpWindowsLocked(); + reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken); + if (DEBUG_REORDER) Slog.v(TAG, "Final window list:"); + if (DEBUG_REORDER) dumpWindowsLocked(); + updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, + false /*updateInputWindows*/); + mLayoutNeeded = true; + mInputMonitor.setUpdateInputWindowsNeededLw(); + performLayoutAndPlaceSurfacesLocked(); + mInputMonitor.updateInputWindowsLw(false /*force*/); + } + Binder.restoreCallingIdentity(origId); } - Binder.restoreCallingIdentity(origId); } } @@ -4705,7 +4753,9 @@ public class WindowManagerService extends IWindowManager.Stub assignLayersLocked(); } mLayoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); + if (!mInLayout) { + performLayoutAndPlaceSurfacesLocked(); + } mInputMonitor.updateInputWindowsLw(false /*force*/); } } @@ -4761,22 +4811,22 @@ public class WindowManagerService extends IWindowManager.Stub "Adding next to top: " + wt); mAppTokens.add(wt); if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { - mToTopApps.remove(wt); - mToBottomApps.remove(wt); - mToTopApps.add(wt); wt.sendingToBottom = false; - wt.sendingToTop = true; } } } - if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) { + if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET + && !mAppTransitionRunning) { + mAnimatingAppTokens.clear(); + mAnimatingAppTokens.addAll(mAppTokens); moveAppWindowsLocked(tokens, mAppTokens.size()); } } Binder.restoreCallingIdentity(origId); } + @Override public void moveAppTokensToBottom(List tokens) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "moveAppTokensToBottom()")) { @@ -4785,8 +4835,14 @@ public class WindowManagerService extends IWindowManager.Stub final long origId = Binder.clearCallingIdentity(); synchronized(mWindowMap) { - removeAppTokensLocked(tokens); final int N = tokens.size(); + if (N > 0 && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET + && !mAppTransitionRunning) { + // animating towards back, hang onto old list for duration of animation. + mAnimatingAppTokens.clear(); + mAnimatingAppTokens.addAll(mAppTokens); + } + removeAppTokensLocked(tokens); int pos = 0; for (int i=0; i 0) { for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { try { @@ -9033,7 +9063,7 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken thisApp = win.mAppToken; // If this window's application has been removed, just skip it. - if (thisApp != null && thisApp.removed) { + if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) { continue; } @@ -9436,6 +9466,21 @@ public class WindowManagerService extends IWindowManager.Stub } } } + if (mAppTransitionRunning && mAnimatingAppTokens.size() > 0) { + pw.println(); + pw.println(" Application tokens during animation:"); + for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) { + WindowToken token = mAnimatingAppTokens.get(i); + pw.print(" App moving to bottom #"); pw.print(i); + pw.print(' '); pw.print(token); + if (dumpAll) { + pw.println(':'); + token.dump(pw, " "); + } else { + pw.println(); + } + } + } pw.println(); if (mOpeningApps.size() > 0) { pw.print(" mOpeningApps="); pw.println(mOpeningApps); @@ -9443,12 +9488,6 @@ public class WindowManagerService extends IWindowManager.Stub if (mClosingApps.size() > 0) { pw.print(" mClosingApps="); pw.println(mClosingApps); } - if (mToTopApps.size() > 0) { - pw.print(" mToTopApps="); pw.println(mToTopApps); - } - if (mToBottomApps.size() > 0) { - pw.print(" mToBottomApps="); pw.println(mToBottomApps); - } } void dumpSessionsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index e2a904feac369..8f2ef7673f3f2 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -841,7 +841,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } - /** Returns true if this window desires key events. */ + /** Returns true if this window desires key events. + * TODO(cmautner): Is this the same as {@link WindowManagerService#canBeImeTarget} + */ public final boolean canReceiveKeys() { return isVisibleOrAdding() && (mViewVisibility == View.VISIBLE) diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index 355db6e079b94..affe5d49abb01 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -403,8 +403,8 @@ class WindowStateAnimator { boolean finishDrawingLocked() { if (mDrawState == DRAW_PENDING) { - if (DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v( - TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in " + if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION) + Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in " + mSurface); mDrawState = COMMIT_DRAW_PENDING; return true; @@ -417,7 +417,7 @@ class WindowStateAnimator { if (mDrawState != COMMIT_DRAW_PENDING) { return false; } - if (DEBUG_ANIM) + if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurface); mDrawState = READY_TO_SHOW; final boolean starting = mWin.mAttrs.type == TYPE_APPLICATION_STARTING; @@ -504,7 +504,9 @@ class WindowStateAnimator { @Override public void setWindowCrop(Rect crop) { super.setWindowCrop(crop); - mWindowCrop.set(crop); + if (crop != null) { + mWindowCrop.set(crop); + } Slog.v(SURFACE_TAG, "setWindowCrop: " + this + ". Called by " + Debug.getCallers(3)); } @@ -1232,7 +1234,8 @@ class WindowStateAnimator { // Force the show in the next prepareSurfaceLocked() call. mLastAlpha = -1; - if (DEBUG_ANIM) Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN"); + if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) + Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this); mDrawState = HAS_DRAWN; mService.scheduleAnimationLocked(); diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/java/com/android/server/wm/WindowToken.java index 3cd256e85054e..5ec151b8e805b 100644 --- a/services/java/com/android/server/wm/WindowToken.java +++ b/services/java/com/android/server/wm/WindowToken.java @@ -71,10 +71,6 @@ class WindowToken { // windows will be put to the bottom of the list. boolean sendingToBottom; - // Set to true when this token is in a pending transaction where its - // windows will be put to the top of the list. - boolean sendingToTop; - WindowToken(WindowManagerService _service, IBinder _token, int type, boolean _explicit) { service = _service; token = _token; @@ -88,11 +84,10 @@ class WindowToken { pw.print(prefix); pw.print("windowType="); pw.print(windowType); pw.print(" hidden="); pw.print(hidden); pw.print(" hasVisible="); pw.println(hasVisible); - if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) { + if (waitingToShow || waitingToHide || sendingToBottom) { pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow); pw.print(" waitingToHide="); pw.print(waitingToHide); pw.print(" sendingToBottom="); pw.print(sendingToBottom); - pw.print(" sendingToTop="); pw.println(sendingToTop); } }