Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8acebe4 authored by Craig Mautner's avatar Craig Mautner Committed by Android (Google) Code Review
Browse files

Merge "Separate animation steps into start, step and finish phases. Fixes bug 6089126."

parents 38addbe3 dbb7991b
Loading
Loading
Loading
Loading
+25 −17
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ import java.util.ArrayList;
 * Version of WindowToken that is specifically for a particular application (or
 * really activity) that is displaying windows.
 */
class AppWindowToken extends WindowToken {
class AppWindowToken extends WindowToken implements WindowManagerService.StepAnimator {
    // Non-null only for application tokens.
    final IApplicationToken appToken;

@@ -195,8 +195,28 @@ class AppWindowToken extends WindowToken {
        }
    }

    @Override
    public boolean stepAnimation(long currentTime) {
        if (animation == null) {
            return false;
        }
        transformation.clear();
        final boolean more = animation.getTransformation(currentTime, transformation);
        if (WindowManagerService.DEBUG_ANIM) Slog.v(
            WindowManagerService.TAG, "Stepped animation in " + this +
            ": more=" + more + ", xform=" + transformation);
        if (!more) {
            animation = null;
            if (WindowManagerService.DEBUG_ANIM) Slog.v(
                WindowManagerService.TAG, "Finished animation in " + this +
                " @ " + currentTime);
        }
        hasTransformation = more;
        return more;
    }

    // This must be called while inside a transaction.
    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
    boolean startAndFinishAnimationLocked(long currentTime, int dw, int dh) {
        if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
            // We will run animations as long as the display isn't frozen.

@@ -219,22 +239,9 @@ class AppWindowToken extends WindowToken {
                    animation.setStartTime(currentTime);
                    animating = true;
                }
                transformation.clear();
                final boolean more = animation.getTransformation(
                    currentTime, transformation);
                if (WindowManagerService.DEBUG_ANIM) Slog.v(
                    WindowManagerService.TAG, "Stepped animation in " + this +
                    ": more=" + more + ", xform=" + transformation);
                if (more) {
                // we're done!
                    hasTransformation = true;
                return true;
            }
                if (WindowManagerService.DEBUG_ANIM) Slog.v(
                    WindowManagerService.TAG, "Finished animation in " + this +
                    " @ " + currentTime);
                animation = null;
            }
        } else if (animation != null) {
            // If the display is frozen, and there is a pending animation,
            // clear it and make sure we run the cleanup code.
@@ -369,6 +376,7 @@ class AppWindowToken extends WindowToken {
        return null;
    }

    @Override
    void dump(PrintWriter pw, String prefix) {
        super.dump(pw, prefix);
        if (appToken != null) {
+70 −55
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;

class ScreenRotationAnimation {
class ScreenRotationAnimation implements WindowManagerService.StepAnimator {
    static final String TAG = "ScreenRotationAnimation";
    static final boolean DEBUG_STATE = false;
    static final boolean DEBUG_TRANSFORMS = false;
@@ -97,6 +97,12 @@ class ScreenRotationAnimation {
    final Matrix mSnapshotFinalMatrix = new Matrix();
    final Matrix mTmpMatrix = new Matrix();
    final float[] mTmpFloats = new float[9];
    private boolean mMoreRotateEnter;
    private boolean mMoreRotateExit;
    private boolean mMoreFinishEnter;
    private boolean mMoreFinishExit;
    private boolean mMoreStartEnter;
    private boolean mMoreStartExit;

    public void printTo(String prefix, PrintWriter pw) {
        pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
@@ -456,34 +462,8 @@ class ScreenRotationAnimation {
                && mRotateEnterAnimation != null || mRotateExitAnimation != null;
    }

    @Override
    public boolean stepAnimation(long now) {
        if (!isAnimating()) {
            if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
            return false;
        }

        if (!mAnimRunning) {
            if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
            if (mStartEnterAnimation != null) {
                mStartEnterAnimation.setStartTime(now);
            }
            if (mStartExitAnimation != null) {
                mStartExitAnimation.setStartTime(now);
            }
            if (mFinishEnterAnimation != null) {
                mFinishEnterAnimation.setStartTime(0);
            }
            if (mFinishExitAnimation != null) {
                mFinishExitAnimation.setStartTime(0);
            }
            if (mRotateEnterAnimation != null) {
                mRotateEnterAnimation.setStartTime(now);
            }
            if (mRotateExitAnimation != null) {
                mRotateExitAnimation.setStartTime(now);
            }
            mAnimRunning = true;
        }

        if (mFinishAnimReady && mFinishAnimStartTime < 0) {
            if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
@@ -493,24 +473,24 @@ class ScreenRotationAnimation {
        // If the start animation is no longer running, we want to keep its
        // transformation intact until the finish animation also completes.

        boolean moreStartExit = false;
        mMoreStartExit = false;
        if (mStartExitAnimation != null) {
            mStartExitTransformation.clear();
            moreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
            mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
            if (!moreStartExit) {
            if (!mMoreStartExit) {
                if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
                mStartExitAnimation.cancel();
                mStartExitAnimation = null;
            }
        }

        boolean moreStartEnter = false;
        mMoreStartEnter = false;
        if (mStartEnterAnimation != null) {
            mStartEnterTransformation.clear();
            moreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
            mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
            if (!moreStartEnter) {
            if (!mMoreStartEnter) {
                if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
                mStartEnterAnimation.cancel();
                mStartEnterAnimation = null;
@@ -521,11 +501,11 @@ class ScreenRotationAnimation {
        if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);

        mFinishExitTransformation.clear();
        boolean moreFinishExit = false;
        mMoreFinishExit = false;
        if (mFinishExitAnimation != null) {
            moreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
            mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
            if (!moreStartExit && !moreFinishExit) {
            if (!mMoreStartExit && !mMoreFinishExit) {
                if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
                mStartExitTransformation.clear();
                mFinishExitAnimation.cancel();
@@ -535,11 +515,11 @@ class ScreenRotationAnimation {
        }

        mFinishEnterTransformation.clear();
        boolean moreFinishEnter = false;
        mMoreFinishEnter = false;
        if (mFinishEnterAnimation != null) {
            moreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
            mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
            if (!moreStartEnter && !moreFinishEnter) {
            if (!mMoreStartEnter && !mMoreFinishEnter) {
                if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
                mStartEnterTransformation.clear();
                mFinishEnterAnimation.cancel();
@@ -549,13 +529,13 @@ class ScreenRotationAnimation {
        }

        mRotateExitTransformation.clear();
        boolean moreRotateExit = false;
        mMoreRotateExit = false;
        if (mRotateExitAnimation != null) {
            moreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
            mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
        }

        if (!moreFinishExit && !moreRotateExit) {
        if (!mMoreFinishExit && !mMoreRotateExit) {
            if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
            mRotateExitAnimation.cancel();
            mRotateExitAnimation = null;
@@ -563,13 +543,13 @@ class ScreenRotationAnimation {
        }

        mRotateEnterTransformation.clear();
        boolean moreRotateEnter = false;
        mMoreRotateEnter = false;
        if (mRotateEnterAnimation != null) {
            moreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
            mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
        }

        if (!moreFinishEnter && !moreRotateEnter) {
        if (!mMoreFinishEnter && !mMoreRotateEnter) {
            if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
            mRotateEnterAnimation.cancel();
            mRotateEnterAnimation = null;
@@ -587,14 +567,25 @@ class ScreenRotationAnimation {
        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);

        if (!moreStartExit && !moreFinishExit && !moreRotateExit) {
        final boolean more = mMoreStartEnter || mMoreStartExit || mMoreFinishEnter
                || mMoreFinishExit || mMoreRotateEnter || mMoreRotateExit || !mFinishAnimReady;

        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);

        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);

        return more;
    }

    void updateSurfaces() {
        if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
            if (mSurface != null) {
                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
                mSurface.hide();
            }
        }

        if (!moreStartEnter && !moreFinishEnter && !moreRotateEnter) {
        if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
            if (mBlackFrame != null) {
                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, hiding black frame");
                mBlackFrame.hide();
@@ -605,15 +596,39 @@ class ScreenRotationAnimation {
            }
        }

        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
    }
    
        final boolean more = moreStartEnter || moreStartExit || moreFinishEnter || moreFinishExit
                || moreRotateEnter || moreRotateExit || !mFinishAnimReady;
    public boolean startAndFinishAnimationLocked(long now) {
        if (!isAnimating()) {
            if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
            return false;
        }

        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
        if (!mAnimRunning) {
            if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
            if (mStartEnterAnimation != null) {
                mStartEnterAnimation.setStartTime(now);
            }
            if (mStartExitAnimation != null) {
                mStartExitAnimation.setStartTime(now);
            }
            if (mFinishEnterAnimation != null) {
                mFinishEnterAnimation.setStartTime(0);
            }
            if (mFinishExitAnimation != null) {
                mFinishExitAnimation.setStartTime(0);
            }
            if (mRotateEnterAnimation != null) {
                mRotateEnterAnimation.setStartTime(now);
            }
            if (mRotateExitAnimation != null) {
                mRotateExitAnimation.setStartTime(now);
            }
            mAnimRunning = true;
        }
        
        return more;
        return true;
    }

    public Transformation getEnterTransformation() {
+55 −15
Original line number Diff line number Diff line
@@ -617,6 +617,18 @@ public class WindowManagerService extends IWindowManager.Stub
    final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
    boolean mAnimationScheduled;

    interface StepAnimator {
        /**
         * Continue the stepping of an ongoing animation. When the animation completes this method
         * must disable the animation on the StepAnimator. 
         * @param currentTime Animation time in milliseconds. Use SystemClock.uptimeMillis().
         * @return True if the animation is still going on, false if the animation has completed
         *      and stepAnimation has cleared the animation locally.
         */
        boolean stepAnimation(long currentTime);
    }
    final ArrayList<StepAnimator> mStepAnimators = new ArrayList<StepAnimator>();
    
    final class DragInputEventReceiver extends InputEventReceiver {
        public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
@@ -7614,6 +7626,20 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    /**
     * Run through each of the animating objects saved in mStepAnimators.
     */
    private void stepAnimations() {
        final long currentTime = SystemClock.uptimeMillis();
        for (final StepAnimator stepAnimator : mStepAnimators) {
            final boolean more = stepAnimator.stepAnimation(currentTime);
            if (DEBUG_ANIM) {
                Slog.v(TAG, "stepAnimations: " + currentTime + ": Stepped " + stepAnimator
                        + (more ? " more" : " done"));
            }
        }
    }
    
    /**
     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
     * Update animations of all applications, including those associated with exiting/removed apps.
@@ -7621,31 +7647,33 @@ public class WindowManagerService extends IWindowManager.Stub
     * @param currentTime The time which animations use for calculating transitions.
     * @param innerDw Width of app window.
     * @param innerDh Height of app window.
     * @return true if rotation has stopped, false otherwise
     */
    private void updateWindowsAppsAndRotationAnimationsLocked(long currentTime,
                                                          int innerDw, int innerDh) {
        int i;
        for (i = mWindows.size() - 1; i >= 0; i--) {
            mInnerFields.mAnimating |= mWindows.get(i).stepAnimationLocked(currentTime);
        }

        final int NAT = mAppTokens.size();
        for (i=0; i<NAT; i++) {
            mInnerFields.mAnimating |=
                    mAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
            final AppWindowToken appToken = mAppTokens.get(i);
            if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
                mStepAnimators.add(appToken);
                mInnerFields.mAnimating = true;
            }
        }
        final int NEAT = mExitingAppTokens.size();
        for (i=0; i<NEAT; i++) {
            mInnerFields.mAnimating |=
                    mExitingAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
            final AppWindowToken appToken = mAppTokens.get(i);
            if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
                mStepAnimators.add(appToken);
                mInnerFields.mAnimating = true;
            }
        }

        if (mScreenRotationAnimation != null) {
            if (mScreenRotationAnimation.isAnimating()) {
                if (mScreenRotationAnimation.stepAnimation(currentTime)) {
                if (mScreenRotationAnimation.startAndFinishAnimationLocked(currentTime)) {
                    mInnerFields.mUpdateRotation = false;
                    mInnerFields.mAnimating = true;
                    mStepAnimators.add(mScreenRotationAnimation);
                } else {
                    mInnerFields.mUpdateRotation = true;
                    mScreenRotationAnimation.kill();
@@ -7704,7 +7732,13 @@ public class WindowManagerService extends IWindowManager.Stub
                }

                final boolean wasAnimating = w.mWasAnimating;
                final boolean nowAnimating = w.mLocalAnimating;
                
                
                final boolean nowAnimating = w.startAndFinishAnimationLocked(currentTime);
                if (nowAnimating) {
                    mStepAnimators.add(w);
                    mInnerFields.mAnimating = true;
                }

                if (DEBUG_WALLPAPER) {
                    Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
@@ -8290,6 +8324,10 @@ public class WindowManagerService extends IWindowManager.Stub
        // difficult because we do need to resize surfaces in some
        // cases while they are hidden such as when first showing a
        // window.
        
        if (mScreenRotationAnimation != null) {
            mScreenRotationAnimation.updateSurfaces();
        }
        boolean displayed = false;

        w.computeShownFrameLocked();
@@ -8562,7 +8600,7 @@ public class WindowManagerService extends IWindowManager.Stub
            // so we want to leave all of them as unblurred (for
            // performance reasons).
            mInnerFields.mObscured = true;
        } else if (canBeSeen && (attrFlags & FLAG_BLUR_BEHIND | FLAG_DIM_BEHIND) != 0) {
        } else if (canBeSeen && (attrFlags & (FLAG_BLUR_BEHIND | FLAG_DIM_BEHIND)) != 0) {
            if (localLOGV) Slog.v(TAG, "Win " + w
                    + ": blurring=" + mInnerFields.mBlurring
                    + " obscured=" + mInnerFields.mObscured);
@@ -8735,6 +8773,7 @@ public class WindowManagerService extends IWindowManager.Stub
                mInnerFields.mWindowAnimationBackground = null;
                mInnerFields.mWindowAnimationBackgroundColor = 0;

                mStepAnimators.clear();
                changes = updateWindowsAndWallpaperLocked(currentTime, dw, dh, innerDw, innerDh);

                if (mInnerFields.mTokenMayBeDrawn) {
@@ -8782,10 +8821,11 @@ public class WindowManagerService extends IWindowManager.Stub

            // Update animations of all applications, including those
            // associated with exiting/removed apps
            mInnerFields.mAnimating = false;

            updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
            
            stepAnimations();

            // THIRD LOOP: Update the surfaces of all windows.

            final boolean someoneLosingFocus = mLosingFocus.size() != 0;
@@ -9667,8 +9707,8 @@ public class WindowManagerService extends IWindowManager.Stub
            pw.println();
            pw.println("  Application tokens in Z order:");
            for (int i=mAppTokens.size()-1; i>=0; i--) {
                pw.print("  App #"); pw.print(i); pw.print(": ");
                        pw.println(mAppTokens.get(i));
                pw.print("  App #"); pw.print(i); pw.println(": ");
                        mAppTokens.get(i).dump(pw, "    ");
            }
        }
        if (mFinishedStarting.size() > 0) {
+21 −15
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ import java.util.ArrayList;
/**
 * A window in the window manager.
 */
final class WindowState implements WindowManagerPolicy.WindowState {
final class WindowState implements WindowManagerPolicy.WindowState,
        WindowManagerService.StepAnimator {
    static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
    static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
    static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
@@ -977,9 +978,26 @@ final class WindowState implements WindowManagerPolicy.WindowState {
        return true;
    }

    @Override
    public boolean stepAnimation(long currentTime) {
        if ((mAnimation == null) || !mLocalAnimating) {
            return false;
        }
        mTransformation.clear();
        final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
        if (WindowManagerService.DEBUG_ANIM) Slog.v(
            WindowManagerService.TAG, "Stepped animation in " + this +
            ": more=" + more + ", xform=" + mTransformation);
        if (!more) {
            mAnimation.cancel();
            mAnimation = null;
        }
        return more;
    }

    // This must be called while inside a transaction.  Returns true if
    // there is more animation to run.
    boolean stepAnimationLocked(long currentTime) {
    boolean startAndFinishAnimationLocked(long currentTime) {
        // Save the animation state as it was before this step so WindowManagerService can tell if
        // we just started or just stopped animating by comparing mWasAnimating with isAnimating().
        mWasAnimating = mAnimating;
@@ -1001,24 +1019,12 @@ final class WindowState implements WindowManagerPolicy.WindowState {
                    mLocalAnimating = true;
                    mAnimating = true;
                }
                mTransformation.clear();
                final boolean more = mAnimation.getTransformation(
                    currentTime, mTransformation);
                if (WindowManagerService.DEBUG_ANIM) Slog.v(
                    WindowManagerService.TAG, "Stepped animation in " + this +
                    ": more=" + more + ", xform=" + mTransformation);
                if (more) {
                    // we're not done!
                if ((mAnimation != null) && mLocalAnimating) {
                    return true;
                }
                if (WindowManagerService.DEBUG_ANIM) Slog.v(
                    WindowManagerService.TAG, "Finished animation in " + this +
                    " @ " + currentTime);

                if (mAnimation != null) {
                    mAnimation.cancel();
                    mAnimation = null;
                }
                //WindowManagerService.this.dump();
            }
            mHasLocalTransformation = false;