From 276a6eb879801e7e7988ecb0e6f29241e9a52724 Mon Sep 17 00:00:00 2001 From: Craig Mautner Date: Tue, 4 Nov 2014 15:32:57 -0800 Subject: [PATCH] When keyguard exits use same anim for all windows The entering animations were only applied to the incoming windows one time. If those windows weren't drawn yet then they never had an animation assigned. Furthermore if a starting window was drawn in time it would get the animation but its main window would not get it if it weren't drawn. Even if an animation were assigned later they wouldn't be synced with each other. This change creates a single animation which is shared by all incoming windows. As windows are drawn they can then animate with the starting window. (Also refactorings to eliminate redundant code and unnecessary variables.) Fixes bug 15991916. Change-Id: I844d102439b6eda8c912108431916e04b12f7298 --- .../policy/impl/PhoneWindowManager.java | 38 ++--- .../com/android/server/wm/WindowAnimator.java | 138 ++++++++++-------- .../server/wm/WindowManagerService.java | 2 +- .../server/wm/WindowStateAnimator.java | 17 +-- 4 files changed, 103 insertions(+), 92 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 792712f66e1b7..b9b96de1a0c60 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -48,6 +48,7 @@ import android.media.Ringtone; import android.media.RingtoneManager; import android.media.session.MediaSessionLegacyHelper; import android.os.Bundle; +import android.os.Debug; import android.os.FactoryTest; import android.os.Handler; import android.os.IBinder; @@ -116,6 +117,7 @@ import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.HashSet; +import java.util.List; import static android.view.WindowManager.LayoutParams.*; import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; @@ -2099,11 +2101,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public void removeStartingWindow(IBinder appToken, View window) { - if (DEBUG_STARTING_WINDOW) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Log.v(TAG, "Removing starting window for " + appToken + ": " + window, e); - } + if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": " + + window + " Callers=" + Debug.getCallers(4)); if (window != null) { WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); @@ -2299,24 +2298,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean goingToNotificationShade) { if (goingToNotificationShade) { return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in); - } else if (onWallpaper) { - Animation a = AnimationUtils.loadAnimation(mContext, - R.anim.lock_screen_behind_enter_wallpaper); - AnimationSet set = (AnimationSet) a; - - // TODO: Use XML interpolators when we have log interpolators available in XML. - set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator); - set.getAnimations().get(1).setInterpolator(mLogDecelerateInterpolator); - return set; - } else { - Animation a = AnimationUtils.loadAnimation(mContext, - R.anim.lock_screen_behind_enter); - AnimationSet set = (AnimationSet) a; - - // TODO: Use XML interpolators when we have log interpolators available in XML. - set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator); - return set; } + + AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ? + R.anim.lock_screen_behind_enter_wallpaper : + R.anim.lock_screen_behind_enter); + + // TODO: Use XML interpolators when we have log interpolators available in XML. + final List animations = set.getAnimations(); + for (int i = animations.size() - 1; i >= 0; --i) { + animations.get(i).setInterpolator(mLogDecelerateInterpolator); + } + + return set; } diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 61ea1e8d061ff..8d931418b9153 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -91,6 +91,9 @@ public class WindowAnimator { boolean mKeyguardGoingAwayToNotificationShade; boolean mKeyguardGoingAwayDisableWindowAnimations; + /** Use one animation for all entering activities after keyguard is dismissed. */ + Animation mPostKeyguardExitAnimation; + // forceHiding states. static final int KEYGUARD_NOT_SHOWN = 0; static final int KEYGUARD_ANIMATING_IN = 1; @@ -220,9 +223,6 @@ public class WindowAnimator { ++mAnimTransactionSequence; final WindowList windows = mService.getWindowListLocked(displayId); - ArrayList unForceHiding = null; - boolean wallpaperInUnForceHiding = false; - WindowState wallpaper = null; if (mKeyguardGoingAway) { for (int i = windows.size() - 1; i >= 0; i--) { @@ -261,6 +261,9 @@ public class WindowAnimator { final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ? null : winShowWhenLocked.mAppToken; + boolean wallpaperInUnForceHiding = false; + ArrayList unForceHiding = null; + WindowState wallpaper = null; for (int i = windows.size() - 1; i >= 0; i--) { WindowState win = windows.get(i); WindowStateAnimator winAnimator = win.mWinAnimator; @@ -327,40 +330,53 @@ public class WindowAnimator { } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) { final boolean hideWhenLocked = !((win.mIsImWindow && showImeOverKeyguard) || (appShowWhenLocked != null && appShowWhenLocked == win.mAppToken)); - final boolean changed; if (((mForceHiding == KEYGUARD_ANIMATING_IN) && (!winAnimator.isAnimating() || hideWhenLocked)) || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) { - changed = win.hideLw(false, false); - if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) - && changed) Slog.v(TAG, "Now policy hidden: " + win); + if (!win.hideLw(false, false)) { + // Was already hidden + continue; + } + if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, + "Now policy hidden: " + win); } else { - changed = win.showLw(false, false); - if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) - && changed) Slog.v(TAG, "Now policy shown: " + win); - if (changed) { - if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 - && win.isVisibleNow() /*w.isReadyForDisplay()*/) { - if (unForceHiding == null) { - unForceHiding = new ArrayList(); - } - unForceHiding.add(winAnimator); - if ((flags & FLAG_SHOW_WALLPAPER) != 0) { - wallpaperInUnForceHiding = true; - } + if (!win.showLw(false, false)) { + // Was already showing. + continue; + } + final boolean visibleNow = win.isVisibleNow(); + if (!visibleNow) { + // Couldn't really show, must showLw() again when win becomes visible. + win.hideLw(false, false); + continue; + } + if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, + "Now policy shown: " + win); + if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) { + if (unForceHiding == null) { + unForceHiding = new ArrayList<>(); } - final WindowState currentFocus = mService.mCurrentFocus; - if (currentFocus == null || currentFocus.mLayer < win.mLayer) { - // We are showing on to of the current - // focus, so re-evaluate focus to make - // sure it is correct. - if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG, - "updateWindowsLocked: setting mFocusMayChange true"); - mService.mFocusMayChange = true; + unForceHiding.add(winAnimator); + if ((flags & FLAG_SHOW_WALLPAPER) != 0) { + wallpaperInUnForceHiding = true; } + } else if (mPostKeyguardExitAnimation != null) { + // We're already in the middle of an animation. Use the existing + // animation to bring in this window. + winAnimator.setAnimation(mPostKeyguardExitAnimation); + winAnimator.keyguardGoingAwayAnimation = true; + } + final WindowState currentFocus = mService.mCurrentFocus; + if (currentFocus == null || currentFocus.mLayer < win.mLayer) { + // We are showing on top of the current + // focus, so re-evaluate focus to make + // sure it is correct. + if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG, + "updateWindowsLocked: setting mFocusMayChange true"); + mService.mFocusMayChange = true; } } - if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) { + if ((flags & FLAG_SHOW_WALLPAPER) != 0) { mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; setPendingLayoutChanges(Display.DEFAULT_DISPLAY, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); @@ -403,42 +419,44 @@ public class WindowAnimator { // If we have windows that are being show due to them no longer // being force-hidden, apply the appropriate animation to them. if (unForceHiding != null) { - boolean startKeyguardExit = true; - for (int i=unForceHiding.size()-1; i>=0; i--) { - Animation a = null; - if (!mKeyguardGoingAwayDisableWindowAnimations) { - a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding, - mKeyguardGoingAwayToNotificationShade); - if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim=" + a - + " for win=" + unForceHiding.get(i)); - } else { - if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for win=" - + unForceHiding.get(i)); - } - if (a != null) { + // This only happens the first time that we detect the keyguard is animating out. + if (mKeyguardGoingAwayDisableWindowAnimations) { + if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for windows"); + } else { + if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim for windows"); + mPostKeyguardExitAnimation = mPolicy.createForceHideEnterAnimation( + wallpaperInUnForceHiding, mKeyguardGoingAwayToNotificationShade); + } + if (mPostKeyguardExitAnimation != null) { + for (int i=unForceHiding.size()-1; i>=0; i--) { final WindowStateAnimator winAnimator = unForceHiding.get(i); - winAnimator.setAnimation(a); + winAnimator.setAnimation(mPostKeyguardExitAnimation); winAnimator.keyguardGoingAwayAnimation = true; - if (startKeyguardExit && mKeyguardGoingAway) { - // Do one time only. - mPolicy.startKeyguardExitAnimation(mCurrentTime + a.getStartOffset(), - a.getDuration()); - mKeyguardGoingAway = false; - startKeyguardExit = false; - } } } + } - // Wallpaper is going away in un-force-hide motion, animate it as well. - if (!wallpaperInUnForceHiding && wallpaper != null - && !mKeyguardGoingAwayDisableWindowAnimations) { - if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away"); - Animation a = mPolicy.createForceHideWallpaperExitAnimation( - mKeyguardGoingAwayToNotificationShade); - if (a != null) { - WindowStateAnimator animator = wallpaper.mWinAnimator; - animator.setAnimation(a); - } + if (mPostKeyguardExitAnimation != null) { + // We're in the midst of a keyguard exit animation. + if (mKeyguardGoingAway) { + mPolicy.startKeyguardExitAnimation(mCurrentTime + + mPostKeyguardExitAnimation.getStartOffset(), + mPostKeyguardExitAnimation.getDuration()); + mKeyguardGoingAway = false; + } else if (mPostKeyguardExitAnimation.hasEnded()) { + // Done with the animation, reset. + mPostKeyguardExitAnimation = null; + } + } + + // Wallpaper is going away in un-force-hide motion, animate it as well. + if (!wallpaperInUnForceHiding && wallpaper != null + && !mKeyguardGoingAwayDisableWindowAnimations) { + if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away"); + Animation a = mPolicy.createForceHideWallpaperExitAnimation( + mKeyguardGoingAwayToNotificationShade); + if (a != null) { + wallpaper.mWinAnimator.setAnimation(a); } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b4e2778a1b7c3..ccb5bfce59038 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -9783,7 +9783,7 @@ public class WindowManagerService extends IWindowManager.Stub if (!w.isDrawnLw()) { Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl + " pv=" + w.mPolicyVisibility - + " mDrawState=" + winAnimator.mDrawState + + " mDrawState=" + winAnimator.drawStateToString() + " ah=" + w.mAttachedHidden + " th=" + atoken.hiddenRequested + " a=" + winAnimator.mAnimating); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index fc3f2c275d2f1..e7c235f95d63a 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -167,14 +167,14 @@ class WindowStateAnimator { private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - static String drawStateToString(int state) { - switch (state) { + String drawStateToString() { + switch (mDrawState) { case NO_SURFACE: return "NO_SURFACE"; case DRAW_PENDING: return "DRAW_PENDING"; case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING"; case READY_TO_SHOW: return "READY_TO_SHOW"; case HAS_DRAWN: return "HAS_DRAWN"; - default: return Integer.toString(state); + default: return Integer.toString(mDrawState); } } int mDrawState; @@ -489,7 +489,7 @@ class WindowStateAnimator { if (DEBUG_STARTING_WINDOW && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState=" - + drawStateToString(mDrawState)); + + drawStateToString()); } if (mDrawState == DRAW_PENDING) { if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION) @@ -510,18 +510,17 @@ class WindowStateAnimator { if (DEBUG_STARTING_WINDOW && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" - + drawStateToString(mDrawState)); + + drawStateToString()); } - if (mDrawState != COMMIT_DRAW_PENDING) { + if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) { return false; } if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) { Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceControl); } mDrawState = READY_TO_SHOW; - final boolean starting = mWin.mAttrs.type == TYPE_APPLICATION_STARTING; final AppWindowToken atoken = mWin.mAppToken; - if (atoken == null || atoken.allDrawn || starting) { + if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) { performShowLocked(); } return true; @@ -1868,7 +1867,7 @@ class WindowStateAnimator { if (dumpAll) { pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl); pw.print(prefix); pw.print("mDrawState="); - pw.print(drawStateToString(mDrawState)); + pw.print(drawStateToString()); pw.print(" mLastHidden="); pw.println(mLastHidden); } pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);