From 24966d4789c7a2054650ec1a5ed7450f0d691224 Mon Sep 17 00:00:00 2001 From: Filip Gruszczynski Date: Sat, 5 Sep 2015 15:00:00 -0700 Subject: [PATCH] Refactorings for Window Manager module. Following improvements were applied: * extract code from a very large method WindowSurfacePlacer.performSurfacePlacementInner into WindowsurfacePlacer.applySurfaceChangesTransaction; smaller methods are easier to understand; * WindowStateAnimator.showSurfaceRobustlyLocked can be privatized, it is only called from one place; also there is unnecessary check for whether mSurfaceControl is not null; * prepareAppTransition code can be mostly moved into AppTransition; it calls mostly methods from this class; as a result some methods from AppTransition can be privatized; * requestTraversalLocked can be moved into WindowSurfacePlacer, which allows mTraversalScheduled to be a private field inside the placer; this way WindowSurfacePlacer can nicely control and hide the need for layouts. Change-Id: I99006c859ef224f5dad933f5c15d2cb2b9738a9e --- .../com/android/server/wm/AppTransition.java | 39 +- .../java/com/android/server/wm/TaskStack.java | 4 +- .../com/android/server/wm/WindowAnimator.java | 18 +- .../server/wm/WindowManagerService.java | 58 +- .../com/android/server/wm/WindowState.java | 2 +- .../server/wm/WindowStateAnimator.java | 19 +- .../server/wm/WindowSurfacePlacer.java | 578 +++++++++--------- 7 files changed, 357 insertions(+), 361 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index c76e64c4ff442..192b168122bda 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -133,6 +133,7 @@ public class AppTransition implements Dump { private static final int DEFAULT_APP_TRANSITION_DURATION = 336; private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336; private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336; + private static final long APP_TRANSITION_TIMEOUT_MS = 5000; private final Context mContext; private final Handler mH; @@ -242,10 +243,6 @@ public class AppTransition implements Dump { return mNextAppTransition != TRANSIT_UNSET; } - boolean isTransitionNone() { - return mNextAppTransition == TRANSIT_NONE; - } - boolean isTransitionEqual(int transit) { return mNextAppTransition == transit; } @@ -254,7 +251,7 @@ public class AppTransition implements Dump { return mNextAppTransition; } - void setAppTransition(int transit) { + private void setAppTransition(int transit) { mNextAppTransition = transit; } @@ -299,7 +296,7 @@ public class AppTransition implements Dump { return mNextAppTransitionScaleUp; } - boolean prepare() { + private boolean prepare() { if (!isRunning()) { mAppTransitionState = APP_STATE_IDLE; notifyAppTransitionPendingLocked(); @@ -1458,4 +1455,34 @@ public class AppTransition implements Dump { public void setCurrentUser(int newUserId) { mCurrentUserId = newUserId; } + + /** + * @return true if transition is not running and should not be skipped, false if transition is + * already running + */ + boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent) { + if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:" + + " transit=" + appTransitionToString(transit) + + " " + this + + " alwaysKeepCurrent=" + alwaysKeepCurrent + + " Callers=" + Debug.getCallers(3)); + if (!isTransitionSet() || mNextAppTransition == TRANSIT_NONE) { + setAppTransition(transit); + } else if (!alwaysKeepCurrent) { + if (transit == TRANSIT_TASK_OPEN && isTransitionEqual(TRANSIT_TASK_CLOSE)) { + // Opening a new task always supersedes a close for the anim. + setAppTransition(transit); + } else if (transit == TRANSIT_ACTIVITY_OPEN + && isTransitionEqual(TRANSIT_ACTIVITY_CLOSE)) { + // Opening a new activity always supersedes a close for the anim. + setAppTransition(transit); + } + } + boolean prepared = prepare(); + if (isTransitionSet()) { + mH.removeMessages(H.APP_TRANSITION_TIMEOUT); + mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, APP_TRANSITION_TIMEOUT_MS); + } + return prepared; + } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index f21f00aefeb27..c3a8486db9ba9 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -25,7 +25,6 @@ import android.graphics.Rect; import android.os.Debug; import android.os.RemoteException; import android.util.EventLog; -import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; import android.view.DisplayInfo; @@ -34,7 +33,6 @@ import com.android.server.EventLogTags; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.List; public class TaskStack implements DimLayer.DimLayerUser { @@ -414,7 +412,7 @@ public class TaskStack implements DimLayer.DimLayerUser { } } if (doAnotherLayoutPass) { - mService.requestTraversalLocked(); + mService.mWindowPlacerLocked.requestTraversal(); } if (mStackId == DOCKED_STACK_ID) { diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index b334a05a45232..ab1bf202f666d 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -57,6 +57,7 @@ public class WindowAnimator { final WindowManagerService mService; final Context mContext; final WindowManagerPolicy mPolicy; + private final WindowSurfacePlacer mWindowPlacerLocked; /** Is any window animating? */ boolean mAnimating; @@ -112,6 +113,7 @@ public class WindowAnimator { mService = service; mContext = service.mContext; mPolicy = service.mPolicy; + mWindowPlacerLocked = service.mWindowPlacerLocked; mAnimationFrameCallback = new Choreographer.FrameCallback() { public void doFrame(long frameTimeNs) { @@ -300,7 +302,7 @@ public class WindowAnimator { setPendingLayoutChanges(Display.DEFAULT_DISPLAY, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.mWindowPlacerLocked.debugLayoutRepeats( + mWindowPlacerLocked.debugLayoutRepeats( "updateWindowsAndWallpaperLocked 2", getPendingLayoutChanges(Display.DEFAULT_DISPLAY)); } @@ -315,7 +317,7 @@ public class WindowAnimator { setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.mWindowPlacerLocked.debugLayoutRepeats( + mWindowPlacerLocked.debugLayoutRepeats( "updateWindowsAndWallpaperLocked 3", getPendingLayoutChanges(displayId)); } @@ -410,7 +412,7 @@ public class WindowAnimator { setPendingLayoutChanges(Display.DEFAULT_DISPLAY, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.mWindowPlacerLocked.debugLayoutRepeats( + mWindowPlacerLocked.debugLayoutRepeats( "updateWindowsAndWallpaperLocked 4", getPendingLayoutChanges(Display.DEFAULT_DISPLAY)); } @@ -435,7 +437,7 @@ public class WindowAnimator { setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.mWindowPlacerLocked.debugLayoutRepeats( + mWindowPlacerLocked.debugLayoutRepeats( "updateWindowsAndWallpaperLocked 5", getPendingLayoutChanges(displayId)); } @@ -741,15 +743,15 @@ public class WindowAnimator { boolean doRequest = false; if (mBulkUpdateParams != 0) { - doRequest = mService.mWindowPlacerLocked.copyAnimToLayoutParamsLocked(); + doRequest = mWindowPlacerLocked.copyAnimToLayoutParamsLocked(); } if (hasPendingLayoutChanges || doRequest) { - mService.requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } if (!mAnimating && wasAnimating) { - mService.requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } if (WindowManagerService.DEBUG_WINDOW_TRACE) { Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating @@ -850,7 +852,7 @@ public class WindowAnimator { if (displayId == windows.get(i).getDisplayId()) { setPendingLayoutChanges(displayId, changes); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.mWindowPlacerLocked.debugLayoutRepeats(reason, + mWindowPlacerLocked.debugLayoutRepeats(reason, getPendingLayoutChanges(displayId)); } break; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 1ccb5924d3ab9..9cc99588018e0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -471,7 +471,6 @@ public class WindowManagerService extends IWindowManager.Stub int mSystemDecorLayer = 0; final Rect mScreenRect = new Rect(); - boolean mTraversalScheduled = false; boolean mDisplayFrozen = false; long mDisplayFreezeTime = 0; int mLastDisplayFreezeDuration = 0; @@ -2773,7 +2772,7 @@ public class WindowManagerService extends IWindowManager.Stub if (displayContent != null) { displayContent.layoutNeeded = true; } - requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } } } finally { @@ -3472,35 +3471,12 @@ public class WindowManagerService extends IWindowManager.Stub "prepareAppTransition()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); } - synchronized(mWindowMap) { - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:" - + " transit=" + AppTransition.appTransitionToString(transit) - + " " + mAppTransition - + " alwaysKeepCurrent=" + alwaysKeepCurrent - + " Callers=" + Debug.getCallers(3)); - if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) { - mAppTransition.setAppTransition(transit); - } else if (!alwaysKeepCurrent) { - if (transit == AppTransition.TRANSIT_TASK_OPEN - && mAppTransition.isTransitionEqual( - AppTransition.TRANSIT_TASK_CLOSE)) { - // Opening a new task always supersedes a close for the anim. - mAppTransition.setAppTransition(transit); - } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN - && mAppTransition.isTransitionEqual( - AppTransition.TRANSIT_ACTIVITY_CLOSE)) { - // Opening a new activity always supersedes a close for the anim. - mAppTransition.setAppTransition(transit); - } - } - if (okToDisplay() && mAppTransition.prepare()) { + boolean prepared = mAppTransition.prepareAppTransitionLocked( + transit, alwaysKeepCurrent); + if (prepared && okToDisplay()) { mSkipAppTransitionAnimation = false; } - if (mAppTransition.isTransitionSet()) { - mH.removeMessages(H.APP_TRANSITION_TIMEOUT); - mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000); - } } } @@ -3836,7 +3812,7 @@ public class WindowManagerService extends IWindowManager.Stub if (atoken != null) { atoken.appFullscreen = toOpaque; setWindowOpaqueLocked(token, toOpaque); - requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } } } @@ -4841,7 +4817,7 @@ public class WindowManagerService extends IWindowManager.Stub mAnimator.mKeyguardGoingAway = true; mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade; mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations; - requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } } @@ -7180,7 +7156,6 @@ public class WindowManagerService extends IWindowManager.Stub case DO_TRAVERSAL: { synchronized(mWindowMap) { - mTraversalScheduled = false; mWindowPlacerLocked.performSurfacePlacement(); } } break; @@ -8463,14 +8438,7 @@ public class WindowManagerService extends IWindowManager.Stub void requestTraversal() { synchronized (mWindowMap) { - requestTraversalLocked(); - } - } - - void requestTraversalLocked() { - if (!mTraversalScheduled) { - mTraversalScheduled = true; - mH.sendEmptyMessage(H.DO_TRAVERSAL); + mWindowPlacerLocked.requestTraversal(); } } @@ -9334,6 +9302,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mInputMethodWindow != null) { pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow); } + mWindowPlacerLocked.dump(pw, " "); mWallpaperControllerLocked.dump(pw, " "); if (mInputMethodAnimLayerAdjustment != 0 || mWallpaperControllerLocked.getAnimLayerAdjustment() != 0) { @@ -9369,8 +9338,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" window="); pw.print(mWindowAnimationScaleSetting); pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); - pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); - pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); + pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation); pw.println(" mLayoutToAnim:"); mAppTransition.dump(pw, " "); } @@ -9728,7 +9696,7 @@ public class WindowManagerService extends IWindowManager.Stub createDisplayContentLocked(display); displayReady(displayId); } - requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } } @@ -9751,7 +9719,7 @@ public class WindowManagerService extends IWindowManager.Stub } } mAnimator.removeDisplayLocked(displayId); - requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } public void onDisplayChanged(int displayId) { @@ -9763,7 +9731,7 @@ public class WindowManagerService extends IWindowManager.Stub if (displayContent != null) { displayContent.updateDisplayInfo(); } - requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } @Override @@ -9910,7 +9878,7 @@ public class WindowManagerService extends IWindowManager.Stub } } } - requestTraversalLocked(); + mWindowPlacerLocked.requestTraversal(); } mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); if (mWaitingForDrawn.isEmpty()) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d756d39121705..779f342719786 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1640,7 +1640,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { Slog.w(TAG, "Failed to report 'resized' to the client of " + this + ", removing this window."); mService.mPendingRemove.add(this); - mService.requestTraversalLocked(); + mService.mWindowPlacerLocked.requestTraversal(); } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 066dc9554ebcd..bf1ab8fab7d04 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1446,7 +1446,7 @@ class WindowStateAnimator { updateSurfaceWindowCrop(recoveringMemory); } - public void prepareSurfaceLocked(final boolean recoveringMemory) { + void prepareSurfaceLocked(final boolean recoveringMemory) { final WindowState w = mWin; if (mSurfaceControl == null) { if (w.mOrientationChanging) { @@ -1782,17 +1782,14 @@ class WindowStateAnimator { * * @return Returns true if the surface was successfully shown. */ - boolean showSurfaceRobustlyLocked() { + private boolean showSurfaceRobustlyLocked() { try { - if (mSurfaceControl != null) { - mSurfaceShown = true; - mSurfaceControl.show(); - if (mWin.mTurnOnScreen) { - if (DEBUG_VISIBILITY) Slog.v(TAG, - "Show surface turning screen on: " + mWin); - mWin.mTurnOnScreen = false; - mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN; - } + mSurfaceShown = true; + mSurfaceControl.show(); + if (mWin.mTurnOnScreen) { + if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin); + mWin.mTurnOnScreen = false; + mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN; } return true; } catch (RuntimeException e) { diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 8582ca28bd4ac..52efa68034992 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -57,6 +57,7 @@ import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import java.io.PrintWriter; import java.util.ArrayList; /** @@ -108,6 +109,8 @@ class WindowSurfacePlacer { private int mPreferredModeId = 0; + private boolean mTraversalScheduled; + public WindowSurfacePlacer(WindowManagerService service) { mService = service; mWallpaperControllerLocked = mService.mWallpaperControllerLocked; @@ -116,11 +119,11 @@ class WindowSurfacePlacer { final void performSurfacePlacement() { int loopCount = 6; do { - mService.mTraversalScheduled = false; + mTraversalScheduled = false; performSurfacePlacementLoop(); mService.mH.removeMessages(DO_TRAVERSAL); loopCount--; - } while (mService.mTraversalScheduled && loopCount > 0); + } while (mTraversalScheduled && loopCount > 0); mWallpaperActionPending = false; } @@ -177,7 +180,7 @@ class WindowSurfacePlacer { if (mService.needsLayout()) { if (++mLayoutRepeatCount < 6) { - mService.requestTraversalLocked(); + requestTraversal(); } else { Slog.e(TAG, "Performed 6 layouts in a row. Skipping"); mLayoutRepeatCount = 0; @@ -257,290 +260,7 @@ class WindowSurfacePlacer { ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); SurfaceControl.openTransaction(); try { - - if (mService.mWatermark != null) { - mService.mWatermark.positionSurface(defaultDw, defaultDh); - } - if (mService.mStrictModeFlash != null) { - mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh); - } - if (mService.mCircularDisplayMask != null) { - mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh, - mService.mRotation); - } - if (mService.mEmulatorDisplayOverlay != null) { - mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, - mService.mRotation); - } - - boolean focusDisplayed = false; - - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); - boolean updateAllDrawn = false; - WindowList windows = displayContent.getWindowList(); - DisplayInfo displayInfo = displayContent.getDisplayInfo(); - final int displayId = displayContent.getDisplayId(); - final int dw = displayInfo.logicalWidth; - final int dh = displayInfo.logicalHeight; - final int innerDw = displayInfo.appWidth; - final int innerDh = displayInfo.appHeight; - final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); - - // Reset for each display. - mDisplayHasContent = false; - mPreferredRefreshRate = 0; - mPreferredModeId = 0; - - int repeats = 0; - do { - repeats++; - if (repeats > 6) { - Slog.w(TAG, "Animation repeat aborted after too many iterations"); - displayContent.layoutNeeded = false; - break; - } - - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( - "On entry to LockedInner", displayContent.pendingLayoutChanges); - - if ((displayContent.pendingLayoutChanges - & FINISH_LAYOUT_REDO_WALLPAPER) != 0 - && mWallpaperControllerLocked.adjustWallpaperWindows()) { - mService.assignLayersLocked(windows); - displayContent.layoutNeeded = true; - } - - if (isDefaultDisplay && (displayContent.pendingLayoutChanges - & FINISH_LAYOUT_REDO_CONFIG) != 0) { - if (DEBUG_LAYOUT) Slog.v(TAG, - "Computing new config from layout"); - if (mService.updateOrientationFromAppTokensLocked(true)) { - displayContent.layoutNeeded = true; - mService.mH.sendEmptyMessage( - SEND_NEW_CONFIGURATION); - } - } - - if ((displayContent.pendingLayoutChanges - & FINISH_LAYOUT_REDO_LAYOUT) != 0) { - displayContent.layoutNeeded = true; - } - - // FIRST LOOP: Perform a layout, if needed. - if (repeats < LAYOUT_REPEAT_THRESHOLD) { - performLayoutLockedInner(displayContent, repeats == 1, - false /*updateInputWindows*/); - } else { - Slog.w(TAG, "Layout repeat skipped after too many iterations"); - } - - // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think - // it is animating. - displayContent.pendingLayoutChanges = 0; - - if (isDefaultDisplay) { - mService.mPolicy.beginPostLayoutPolicyLw(dw, dh); - for (i = windows.size() - 1; i >= 0; i--) { - WindowState w = windows.get(i); - if (w.mHasSurface) { - mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, - w.mAttachedWindow); - } - } - displayContent.pendingLayoutChanges |= - mService.mPolicy.finishPostLayoutPolicyLw(); - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( - "after finishPostLayoutPolicyLw", - displayContent.pendingLayoutChanges); - } - } while (displayContent.pendingLayoutChanges != 0); - - mObscured = false; - mSyswin = false; - displayContent.resetDimming(); - - // Only used if default window - final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); - - final int N = windows.size(); - for (i=N-1; i>=0; i--) { - WindowState w = windows.get(i); - final Task task = w.getTask(); - if (task == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) { - continue; - } - - final boolean obscuredChanged = w.mObscured != mObscured; - - // Update effect. - w.mObscured = mObscured; - if (!mObscured) { - handleNotObscuredLocked(w, innerDw, innerDh); - } - - if (task != null && !task.getContinueDimming()) { - w.handleFlagDimBehind(); - } - - if (isDefaultDisplay && obscuredChanged - && mWallpaperControllerLocked.isWallpaperTarget(w) - && w.isVisibleLw()) { - // This is the wallpaper target and its obscured state - // changed... make sure the current wallaper's visibility - // has been updated accordingly. - mWallpaperControllerLocked.updateWallpaperVisibility(); - } - - final WindowStateAnimator winAnimator = w.mWinAnimator; - - // If the window has moved due to its containing content frame changing, then - // notify the listeners and optionally animate it. - if (w.hasMoved()) { - // Frame has moved, containing content frame has also moved, and we're not - // currently animating... let's do something. - final int left = w.mFrame.left; - final int top = w.mFrame.top; - if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0) { - Animation a = AnimationUtils.loadAnimation(mService.mContext, - com.android.internal.R.anim.window_move_from_decor); - winAnimator.setAnimation(a); - winAnimator.mAnimDw = w.mLastFrame.left - left; - winAnimator.mAnimDh = w.mLastFrame.top - top; - winAnimator.mAnimateMove = true; - winAnimator.mAnimatingMove = true; - } - - //TODO (multidisplay): Accessibility supported only for the default display. - if (mService.mAccessibilityController != null - && displayId == Display.DEFAULT_DISPLAY) { - mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); - } - - try { - w.mClient.moved(left, top); - } catch (RemoteException e) { - } - } - - //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. - final boolean committed = winAnimator.commitFinishDrawingLocked(); - if (isDefaultDisplay && committed) { - if (w.mAttrs.type == TYPE_DREAM) { - // HACK: When a dream is shown, it may at that - // point hide the lock screen. So we need to - // redo the layout to let the phone window manager - // make this happen. - displayContent.pendingLayoutChanges |= - FINISH_LAYOUT_REDO_LAYOUT; - if (DEBUG_LAYOUT_REPEATS) { - debugLayoutRepeats( - "dream and commitFinishDrawingLocked true", - displayContent.pendingLayoutChanges); - } - } - if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { - if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, - "First draw done in potential wallpaper target " + w); - mWallpaperMayChange = true; - displayContent.pendingLayoutChanges |= - FINISH_LAYOUT_REDO_WALLPAPER; - if (DEBUG_LAYOUT_REPEATS) { - debugLayoutRepeats( - "wallpaper and commitFinishDrawingLocked true", - displayContent.pendingLayoutChanges); - } - } - } - - winAnimator.setSurfaceBoundariesLocked(recoveringMemory); - } - - final AppWindowToken atoken = w.mAppToken; - if (DEBUG_STARTING_WINDOW && atoken != null - && w == atoken.startingWindow) { - Slog.d(TAG, "updateWindows: starting " + w - + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn - + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); - } - if (atoken != null - && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { - if (atoken.lastTransactionSequence != mService.mTransactionSequence) { - atoken.lastTransactionSequence = mService.mTransactionSequence; - atoken.numInterestingWindows = atoken.numDrawnWindows = 0; - atoken.startingDisplayed = false; - } - if ((w.isOnScreenIgnoringKeyguard() - || winAnimator.mAttrType == TYPE_BASE_APPLICATION) - && !w.mExiting && !w.mDestroying) { - if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { - Slog.v(TAG, "Eval win " + w + ": isDrawn=" - + w.isDrawnLw() - + ", isAnimating=" + winAnimator.isAnimating()); - if (!w.isDrawnLw()) { - Slog.v(TAG, "Not displayed: s=" - + winAnimator.mSurfaceControl - + " pv=" + w.mPolicyVisibility - + " mDrawState=" + winAnimator.drawStateToString() - + " ah=" + w.mAttachedHidden - + " th=" + atoken.hiddenRequested - + " a=" + winAnimator.mAnimating); - } - } - if (w != atoken.startingWindow) { - if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { - atoken.numInterestingWindows++; - if (w.isDrawnLw()) { - atoken.numDrawnWindows++; - if (DEBUG_VISIBILITY - || DEBUG_ORIENTATION) - Slog.v(TAG, - "tokenMayBeDrawn: " + atoken - + " freezingScreen=" - + atoken.mAppAnimator.freezingScreen - + " mAppFreezing=" + w.mAppFreezing); - updateAllDrawn = true; - } - } - } else if (w.isDrawnLw()) { - atoken.startingDisplayed = true; - } - } - } - - if (isDefaultDisplay && someoneLosingFocus && (w == mService.mCurrentFocus) - && w.isDisplayedLw()) { - focusDisplayed = true; - } - - mService.updateResizingWindows(w); - } - - mService.mDisplayManagerInternal.setDisplayProperties(displayId, - mDisplayHasContent, - mPreferredRefreshRate, - mPreferredModeId, - true /* inTraversal, must call performTraversalInTrans... below */); - - mService.getDisplayContentLocked(displayId).stopDimmingIfNeeded(); - - if (updateAllDrawn) { - updateAllDrawnLocked(displayContent); - } - } - - if (focusDisplayed) { - mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS); - } - - // Give the display manager a chance to adjust properties - // like display rotation if it needs to. - mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); + applySurfaceChangesTransaction(recoveringMemory, numDisplays, defaultDw, defaultDh); } catch (RuntimeException e) { Slog.wtf(TAG, "Unhandled exception in Window Manager", e); } finally { @@ -801,6 +521,279 @@ class WindowSurfacePlacer { } } + private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays, + int defaultDw, int defaultDh) { + if (mService.mWatermark != null) { + mService.mWatermark.positionSurface(defaultDw, defaultDh); + } + if (mService.mStrictModeFlash != null) { + mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh); + } + if (mService.mCircularDisplayMask != null) { + mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh, + mService.mRotation); + } + if (mService.mEmulatorDisplayOverlay != null) { + mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, + mService.mRotation); + } + + boolean focusDisplayed = false; + + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); + boolean updateAllDrawn = false; + WindowList windows = displayContent.getWindowList(); + DisplayInfo displayInfo = displayContent.getDisplayInfo(); + final int displayId = displayContent.getDisplayId(); + final int dw = displayInfo.logicalWidth; + final int dh = displayInfo.logicalHeight; + final int innerDw = displayInfo.appWidth; + final int innerDh = displayInfo.appHeight; + final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); + + // Reset for each display. + mDisplayHasContent = false; + mPreferredRefreshRate = 0; + mPreferredModeId = 0; + + int repeats = 0; + do { + repeats++; + if (repeats > 6) { + Slog.w(TAG, "Animation repeat aborted after too many iterations"); + displayContent.layoutNeeded = false; + break; + } + + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats( + "On entry to LockedInner", displayContent.pendingLayoutChanges); + + if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0 && + mWallpaperControllerLocked.adjustWallpaperWindows()) { + mService.assignLayersLocked(windows); + displayContent.layoutNeeded = true; + } + + if (isDefaultDisplay + && (displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) { + if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); + if (mService.updateOrientationFromAppTokensLocked(true)) { + displayContent.layoutNeeded = true; + mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION); + } + } + + if ((displayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) { + displayContent.layoutNeeded = true; + } + + // FIRST LOOP: Perform a layout, if needed. + if (repeats < LAYOUT_REPEAT_THRESHOLD) { + performLayoutLockedInner(displayContent, repeats == 1, + false /* updateInputWindows */); + } else { + Slog.w(TAG, "Layout repeat skipped after too many iterations"); + } + + // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think + // it is animating. + displayContent.pendingLayoutChanges = 0; + + if (isDefaultDisplay) { + mService.mPolicy.beginPostLayoutPolicyLw(dw, dh); + for (int i = windows.size() - 1; i >= 0; i--) { + WindowState w = windows.get(i); + if (w.mHasSurface) { + mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, + w.mAttachedWindow); + } + } + displayContent.pendingLayoutChanges |= + mService.mPolicy.finishPostLayoutPolicyLw(); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw", + displayContent.pendingLayoutChanges); + } + } while (displayContent.pendingLayoutChanges != 0); + + mObscured = false; + mSyswin = false; + displayContent.resetDimming(); + + // Only used if default window + final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty(); + + for (int i = windows.size() - 1; i >= 0; i--) { + WindowState w = windows.get(i); + final Task task = w.getTask(); + if (task == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) { + continue; + } + + final boolean obscuredChanged = w.mObscured != mObscured; + + // Update effect. + w.mObscured = mObscured; + if (!mObscured) { + handleNotObscuredLocked(w, innerDw, innerDh); + } + + if (task != null && !task.getContinueDimming()) { + w.handleFlagDimBehind(); + } + + if (isDefaultDisplay && obscuredChanged + && mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) { + // This is the wallpaper target and its obscured state + // changed... make sure the current wallaper's visibility + // has been updated accordingly. + mWallpaperControllerLocked.updateWallpaperVisibility(); + } + + final WindowStateAnimator winAnimator = w.mWinAnimator; + + // If the window has moved due to its containing content frame changing, then + // notify the listeners and optionally animate it. + if (w.hasMoved()) { + // Frame has moved, containing content frame has also moved, and we're not + // currently animating... let's do something. + final int left = w.mFrame.left; + final int top = w.mFrame.top; + if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0) { + Animation a = AnimationUtils.loadAnimation(mService.mContext, + com.android.internal.R.anim.window_move_from_decor); + winAnimator.setAnimation(a); + winAnimator.mAnimDw = w.mLastFrame.left - left; + winAnimator.mAnimDh = w.mLastFrame.top - top; + winAnimator.mAnimateMove = true; + winAnimator.mAnimatingMove = true; + } + + //TODO (multidisplay): Accessibility supported only for the default display. + if (mService.mAccessibilityController != null + && displayId == Display.DEFAULT_DISPLAY) { + mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(); + } + + try { + w.mClient.moved(left, top); + } catch (RemoteException e) { + } + } + + //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. + final boolean committed = winAnimator.commitFinishDrawingLocked(); + if (isDefaultDisplay && committed) { + if (w.mAttrs.type == TYPE_DREAM) { + // HACK: When a dream is shown, it may at that + // point hide the lock screen. So we need to + // redo the layout to let the phone window manager + // make this happen. + displayContent.pendingLayoutChanges |= + FINISH_LAYOUT_REDO_LAYOUT; + if (DEBUG_LAYOUT_REPEATS) { + debugLayoutRepeats("dream and commitFinishDrawingLocked true", + displayContent.pendingLayoutChanges); + } + } + if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) { + if (DEBUG_WALLPAPER_LIGHT) + Slog.v(TAG, "First draw done in potential wallpaper target " + w); + mWallpaperMayChange = true; + displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; + if (DEBUG_LAYOUT_REPEATS) { + debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true", + displayContent.pendingLayoutChanges); + } + } + } + + winAnimator.setSurfaceBoundariesLocked(recoveringMemory); + } + + final AppWindowToken atoken = w.mAppToken; + if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) { + Slog.d(TAG, "updateWindows: starting " + w + + " isOnScreen=" + w.isOnScreen() + " allDrawn=" + atoken.allDrawn + + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); + } + if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { + if (atoken.lastTransactionSequence != mService.mTransactionSequence) { + atoken.lastTransactionSequence = mService.mTransactionSequence; + atoken.numInterestingWindows = atoken.numDrawnWindows = 0; + atoken.startingDisplayed = false; + } + if ((w.isOnScreenIgnoringKeyguard() + || winAnimator.mAttrType == TYPE_BASE_APPLICATION) + && !w.mExiting && !w.mDestroying) { + if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { + Slog.v(TAG, "Eval win " + w + ": isDrawn=" + + w.isDrawnLw() + + ", isAnimating=" + winAnimator.isAnimating()); + if (!w.isDrawnLw()) { + Slog.v(TAG, "Not displayed: s=" + + winAnimator.mSurfaceControl + + " pv=" + w.mPolicyVisibility + + " mDrawState=" + winAnimator.drawStateToString() + + " ah=" + w.mAttachedHidden + + " th=" + atoken.hiddenRequested + + " a=" + winAnimator.mAnimating); + } + } + if (w != atoken.startingWindow) { + if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { + atoken.numInterestingWindows++; + if (w.isDrawnLw()) { + atoken.numDrawnWindows++; + if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) + Slog.v(TAG, "tokenMayBeDrawn: " + atoken + + " freezingScreen=" + + atoken.mAppAnimator.freezingScreen + + " mAppFreezing=" + w.mAppFreezing); + updateAllDrawn = true; + } + } + } else if (w.isDrawnLw()) { + atoken.startingDisplayed = true; + } + } + } + + if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus + && w.isDisplayedLw()) { + focusDisplayed = true; + } + + mService.updateResizingWindows(w); + } + + mService.mDisplayManagerInternal.setDisplayProperties(displayId, + mDisplayHasContent, + mPreferredRefreshRate, + mPreferredModeId, + true /* inTraversal, must call performTraversalInTrans... below */); + + mService.getDisplayContentLocked(displayId).stopDimmingIfNeeded(); + + if (updateAllDrawn) { + updateAllDrawnLocked(displayContent); + } + } + + if (focusDisplayed) { + mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS); + } + + // Give the display manager a chance to adjust properties + // like display rotation if it needs to. + mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager(); + } + boolean isInLayout() { return mInLayout; } @@ -1514,4 +1507,15 @@ class WindowSurfacePlacer { return doRequest; } + + void requestTraversal() { + if (!mTraversalScheduled) { + mTraversalScheduled = true; + mService.mH.sendEmptyMessage(DO_TRAVERSAL); + } + } + + public void dump(PrintWriter pw, String prefix) { + pw.print(prefix); pw.print("mTraversalScheduled="); pw.println(mTraversalScheduled); + } }