From 3255a28b6a18bb97f0e533dc1673c5e28837b4f2 Mon Sep 17 00:00:00 2001 From: Craig Mautner Date: Mon, 16 Apr 2012 15:42:47 -0700 Subject: [PATCH 1/2] Clear orientation variable until rotation is done. In the old code orientationChangeComplete was set to true on each pass through perfomLayout. If any window was rotating the variable was set to false on the way through the performLayout. Since we can now make passes through performLayout before any animation step occurs we were seeing mOrientationChangeComplete true prior to rotation completing. This change sets mOrientationChangeComplete false at the start of a rotation and sets it to true if we ever get through an animation step without encountering any rotating windows. Change-Id: I37690cf20868dfbaac94a81640bc4d9cb9fb8f00 --- .../java/com/android/server/wm/ScreenRotationAnimation.java | 5 +++++ .../java/com/android/server/wm/WindowManagerService.java | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index 11af6ea1ab795..13013a8d776ef 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -121,6 +121,7 @@ class ScreenRotationAnimation { private boolean mMoreStartEnter; private boolean mMoreStartExit; private boolean mMoreStartFrame; + long mHalfwayPoint; public void printTo(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("mSurface="); pw.print(mSurface); @@ -655,6 +656,9 @@ class ScreenRotationAnimation { } private boolean stepAnimation(long now) { + if (now > mHalfwayPoint) { + mHalfwayPoint = Long.MAX_VALUE; + } if (mFinishAnimReady && mFinishAnimStartTime < 0) { if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready"); mFinishAnimStartTime = now; @@ -915,6 +919,7 @@ class ScreenRotationAnimation { mRotateExitAnimation.setStartTime(now); } mAnimRunning = true; + mHalfwayPoint = now + mRotateEnterAnimation.getDuration() / 2; } return stepAnimation(now); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 0fe6921add065..c712bc9d46454 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -4180,6 +4180,7 @@ public class WindowManagerService extends IWindowManager.Stub if (w.mHasSurface && !w.mOrientationChanging) { if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w); w.mOrientationChanging = true; + mInnerFields.mOrientationChangeComplete = false; } unfrozeWindows = true; } @@ -5485,6 +5486,7 @@ public class WindowManagerService extends IWindowManager.Stub if (w.mHasSurface) { if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w); w.mOrientationChanging = true; + mInnerFields.mOrientationChangeComplete = false; } } for (int i=mRotationWatchers.size()-1; i>=0; i--) { @@ -7589,6 +7591,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w); w.mOrientationChanging = true; + mInnerFields.mOrientationChangeComplete = false; if (!mWindowsFreezingScreen) { mWindowsFreezingScreen = true; // XXX should probably keep timeout from @@ -8059,7 +8062,8 @@ public class WindowManagerService extends IWindowManager.Stub private final void performLayoutAndPlaceSurfacesLockedInner( boolean recoveringMemory) { if (DEBUG_WINDOW_TRACE) { - Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry"); + Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " + + getCallers(3)); } if (mDisplay == null) { Slog.i(TAG, "skipping performLayoutAndPlaceSurfacesLockedInner with no mDisplay"); From acaf9cca865902e6f1823e771f4234bfda53cfd1 Mon Sep 17 00:00:00 2001 From: Craig Mautner Date: Tue, 17 Apr 2012 11:45:25 -0700 Subject: [PATCH 2/2] Move Surface operations into existing transaction. Several Surface operations - notably setPosition, setSize, and show - had been moved outside of a Surface.openTransaction/closeTransaction window. This corrects that problem. In addition, before animations were separated from layout the Surface frame was computed prior to returning from relayoutWindow(). After separation the frame was being computed during animation. This checkin restores the frame calculation in layout. Fixes bug 6343291. Change-Id: I4752bdf1fed0f2b46c5eb9508825c9b1b0fd702f --- .../server/wm/WindowManagerService.java | 134 +++++++++--------- .../server/wm/WindowStateAnimator.java | 45 ++++-- 2 files changed, 96 insertions(+), 83 deletions(-) diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index c712bc9d46454..b8fca611e0ac2 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -7959,7 +7959,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.v(TAG, "Resize reasons: " + " contentInsetsChanged=" + w.mContentInsetsChanged + " visibleInsetsChanged=" + w.mVisibleInsetsChanged - + " surfaceResized=" + w.mWinAnimator.mSurfaceResized + + " surfaceResized=" + winAnimator.mSurfaceResized + " configChanged=" + configChanged); } @@ -7974,7 +7974,7 @@ public class WindowManagerService extends IWindowManager.Stub if (w.mOrientationChanging) { if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation start waiting for draw in " - + w + ", surface " + w.mWinAnimator.mSurface); + + w + ", surface " + winAnimator.mSurface); winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING; if (w.mAppToken != null) { w.mAppToken.allDrawn = false; @@ -7982,15 +7982,15 @@ public class WindowManagerService extends IWindowManager.Stub } if (!mResizingWindows.contains(w)) { if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, - "Resizing window " + w + " to " + w.mWinAnimator.mSurfaceW - + "x" + w.mWinAnimator.mSurfaceH); + "Resizing window " + w + " to " + winAnimator.mSurfaceW + + "x" + winAnimator.mSurfaceH); mResizingWindows.add(w); } } else if (w.mOrientationChanging) { if (w.isDrawnLw()) { if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation not waiting for draw in " - + w + ", surface " + w.mWinAnimator.mSurface); + + w + ", surface " + winAnimator.mSurface); w.mOrientationChanging = false; } } @@ -8083,7 +8083,7 @@ public class WindowManagerService extends IWindowManager.Stub updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); } - + // Initialize state of exiting tokens. for (i=mExitingTokens.size()-1; i>=0; i--) { mExitingTokens.get(i).hasVisible = false; @@ -8112,7 +8112,7 @@ public class WindowManagerService extends IWindowManager.Stub try { int repeats = 0; - + do { repeats++; if (repeats > 6) { @@ -8172,7 +8172,7 @@ public class WindowManagerService extends IWindowManager.Stub mInnerFields.mObscured = false; mInnerFields.mDimming = false; mInnerFields.mSyswin = false; - + boolean focusDisplayed = false; final int N = mWindows.size(); for (i=N-1; i>=0; i--) { @@ -8196,7 +8196,52 @@ public class WindowManagerService extends IWindowManager.Stub // has been updated accordingly. updateWallpaperVisibilityLocked(); } + + final WindowStateAnimator winAnimator = w.mWinAnimator; + + // If the window has moved due to its containing + // content frame changing, then we'd like to animate + // it. + if (w.mHasSurface && w.shouldAnimateMove()) { + // Frame has moved, containing content frame + // has also moved, and we're not currently animating... + // let's do something. + Animation a = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.window_move_from_decor); + winAnimator.setAnimation(a); + winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; + winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; + } else { + winAnimator.mAnimDw = innerDw; + winAnimator.mAnimDh = innerDh; + } + + //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); + w.mContentChanged = false; + + // Moved from updateWindowsAndWallpaperLocked(). + if (w.mHasSurface) { + // Take care of the window being ready to display. + if (winAnimator.commitFinishDrawingLocked(currentTime)) { + if ((w.mAttrs.flags + & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { + if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, + "First draw done in potential wallpaper target " + w); + mInnerFields.mWallpaperMayChange = true; + mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { + debugLayoutRepeats("updateWindowsAndWallpaperLocked 1", + mPendingLayoutChanges); + } + } + } + + winAnimator.setSurfaceBoundaries(recoveringMemory); + } + + updateResizingWindows(w); } + if (focusDisplayed) { mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); } @@ -8278,68 +8323,10 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges); } - final int N = mWindows.size(); - for (i=N-1; i>=0; i--) { - final WindowState w = mWindows.get(i); - final WindowStateAnimator winAnimator = w.mWinAnimator; - - // If the window has moved due to its containing - // content frame changing, then we'd like to animate - // it. - if (w.mHasSurface && w.shouldAnimateMove()) { - // Frame has moved, containing content frame - // has also moved, and we're not currently animating... - // let's do something. - Animation a = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.window_move_from_decor); - winAnimator.setAnimation(a); - winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; - winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; - } else { - winAnimator.mAnimDw = innerDw; - winAnimator.mAnimDh = innerDh; - } - - //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); - w.mContentChanged = false; - - // TODO(cmautner): Can this move up to the loop at the end of try/catch above? - updateResizingWindows(w); - - // Moved from updateWindowsAndWallpaperLocked(). - if (w.mHasSurface) { - // Take care of the window being ready to display. - if (winAnimator.commitFinishDrawingLocked(currentTime)) { - if ((w.mAttrs.flags - & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { - if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, - "First draw done in potential wallpaper target " + w); - mInnerFields.mWallpaperMayChange = true; - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - debugLayoutRepeats("updateWindowsAndWallpaperLocked 1", - mPendingLayoutChanges); - } - } - } - } - } - - if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, - "With display frozen, orientationChangeComplete=" - + mInnerFields.mOrientationChangeComplete); - if (mInnerFields.mOrientationChangeComplete) { - if (mWindowsFreezingScreen) { - mWindowsFreezingScreen = false; - mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); - } - stopFreezingDisplayLocked(); - } - if (!mResizingWindows.isEmpty()) { for (i = mResizingWindows.size() - 1; i >= 0; i--) { WindowState win = mResizingWindows.get(i); - final WindowStateAnimator winAnimator = win.mWinAnimator; + final WindowStateAnimator winAnimator = win.mWinAnimator; try { if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + win + ": " + win.mCompatFrame); @@ -8358,7 +8345,7 @@ public class WindowManagerService extends IWindowManager.Stub win.mConfiguration = mCurConfiguration; if (DEBUG_ORIENTATION && winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i( - TAG, "Resizing " + win + " WITH DRAW PENDING"); + TAG, "Resizing " + win + " WITH DRAW PENDING"); win.mClient.resized((int)winAnimator.mSurfaceW, (int)winAnimator.mSurfaceH, win.mLastContentInsets, win.mLastVisibleInsets, @@ -8374,6 +8361,17 @@ public class WindowManagerService extends IWindowManager.Stub mResizingWindows.clear(); } + if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG, + "With display frozen, orientationChangeComplete=" + + mInnerFields.mOrientationChangeComplete); + if (mInnerFields.mOrientationChangeComplete) { + if (mWindowsFreezingScreen) { + mWindowsFreezingScreen = false; + mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); + } + stopFreezingDisplayLocked(); + } + // Destroy the surface of any windows that are no longer visible. boolean wallpaperDestroyed = false; i = mDestroySurface.size(); diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index 90b63a6a3c297..b61ccbfabf404 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -499,6 +499,14 @@ class WindowStateAnimator { sSurfaces.remove(this); } + @Override + public void release() { + super.release(); + Slog.v(SURFACE_TAG, "release: " + this + ". Called by " + + WindowManagerService.getCallers(3)); + sSurfaces.remove(this); + } + static void dumpAllSurfaces() { final int N = sSurfaces.size(); for (int i = 0; i < N; i++) { @@ -886,22 +894,8 @@ class WindowStateAnimator { mDtDy = mWin.mGlobalScale; } - public void prepareSurfaceLocked(final boolean recoveringMemory) { + void setSurfaceBoundaries(final boolean recoveringMemory) { final WindowState w = mWin; - if (mSurface == null) { - if (w.mOrientationChanging) { - if (DEBUG_ORIENTATION) { - Slog.v(TAG, "Orientation change skips hidden " + w); - } - w.mOrientationChanging = false; - } - return; - } - - boolean displayed = false; - - computeShownFrameLocked(); - int width, height; if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) { // for a scaled surface, we just want to use @@ -950,6 +944,8 @@ class WindowStateAnimator { "SIZE " + width + "x" + height, null); mSurfaceResized = true; mSurface.setSize(width, height); + mAnimator.mPendingLayoutChanges |= + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; } catch (RuntimeException e) { // If something goes wrong with the surface (such // as running out of memory), don't take down the @@ -961,6 +957,25 @@ class WindowStateAnimator { } } } + } + + public void prepareSurfaceLocked(final boolean recoveringMemory) { + final WindowState w = mWin; + if (mSurface == null) { + if (w.mOrientationChanging) { + if (DEBUG_ORIENTATION) { + Slog.v(TAG, "Orientation change skips hidden " + w); + } + w.mOrientationChanging = false; + } + return; + } + + boolean displayed = false; + + computeShownFrameLocked(); + + setSurfaceBoundaries(recoveringMemory); if (w.mAttachedHidden || !w.isReadyForDisplay()) { if (!mLastHidden) {