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

Commit 1caa399b authored by Craig Mautner's avatar Craig Mautner
Browse files

Move animation step from layout to animator.

Set up the Choreographer call from the animator, not from the
layout side. Introduce new class for transferring information from
layout to animator.

Change-Id: I7da032990f4b5eaeefcf92185901d896f25db3d2
parent c4e9ac43
Loading
Loading
Loading
Loading
+62 −6
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@ import android.content.Context;
import android.os.SystemClock;
import android.os.SystemClock;
import android.util.Log;
import android.util.Log;
import android.util.Slog;
import android.util.Slog;
import android.view.Choreographer;
import android.view.Surface;
import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import android.view.WindowManagerPolicy;
@@ -35,6 +36,8 @@ public class WindowAnimator {
    final Context mContext;
    final Context mContext;
    final WindowManagerPolicy mPolicy;
    final WindowManagerPolicy mPolicy;


    final Choreographer mChoreographer = Choreographer.getInstance();

    ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
    ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();


    boolean mAnimating;
    boolean mAnimating;
@@ -50,6 +53,18 @@ public class WindowAnimator {
    }
    }
    InnerLoopParams mInner = new InnerLoopParams();
    InnerLoopParams mInner = new InnerLoopParams();


    static class LayoutToAnimatorParams {
        boolean mAnimationScheduled;
        ArrayList<WindowStateAnimator> mWinAnimators = new ArrayList<WindowStateAnimator>();
        WindowState mWallpaperTarget;
    }
    /** Params from WindowManagerService. Do not modify or read without first locking on
     * either WindowManagerService.mWindowMap or WindowManagerService.mAnimator.and then on
     * mLayoutToAnim */
    final LayoutToAnimatorParams mLayoutToAnim = new LayoutToAnimatorParams();

    final Runnable mAnimationRunnable;

    int mAdjResult;
    int mAdjResult;


    int mPendingLayoutChanges;
    int mPendingLayoutChanges;
@@ -86,11 +101,48 @@ public class WindowAnimator {
    static final int WALLPAPER_ACTION_PENDING = 1;
    static final int WALLPAPER_ACTION_PENDING = 1;
    int mPendingActions;
    int mPendingActions;


    WindowState mWallpaperTarget = null;

    WindowAnimator(final WindowManagerService service, final Context context,
    WindowAnimator(final WindowManagerService service, final Context context,
            final WindowManagerPolicy policy) {
            final WindowManagerPolicy policy) {
        mService = service;
        mService = service;
        mContext = context;
        mContext = context;
        mPolicy = policy;
        mPolicy = policy;

        mAnimationRunnable = new Runnable() {
            @Override
            public void run() {
                // TODO(cmautner): When full isolation is achieved for animation, the first lock
                // goes away and only the WindowAnimator.this remains.
                synchronized(mService.mWindowMap) {
                    synchronized(WindowAnimator.this) {
                        copyLayoutToAnimParamsLocked();
                        animateLocked();
                    }
                }
            }
        };
    }

    /** Copy all WindowManagerService params into local params here. Locked on 'this'. */
    private void copyLayoutToAnimParamsLocked() {
        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
        synchronized(layoutToAnim) {
            layoutToAnim.mAnimationScheduled = false;

            mWinAnimators = new ArrayList<WindowStateAnimator>(layoutToAnim.mWinAnimators);
            mWallpaperTarget = layoutToAnim.mWallpaperTarget;
        }
    }

    /** Note that Locked in this case is on mLayoutToAnim */
    void scheduleAnimationLocked() {
        final LayoutToAnimatorParams layoutToAnim = mLayoutToAnim;
        if (!layoutToAnim.mAnimationScheduled) {
            layoutToAnim.mAnimationScheduled = true;
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null);
        }
    }
    }


    void hideWallpapersLocked(final WindowState w) {
    void hideWallpapersLocked(final WindowState w) {
@@ -128,11 +180,11 @@ public class WindowAnimator {
            if (mService.mWallpaperTarget == target
            if (mService.mWallpaperTarget == target
                    || mService.mLowerWallpaperTarget == target
                    || mService.mLowerWallpaperTarget == target
                    || mService.mUpperWallpaperTarget == target) {
                    || mService.mUpperWallpaperTarget == target) {
                final int N = mService.mWindows.size();
                final int N = mWinAnimators.size();
                for (int i = 0; i < N; i++) {
                for (int i = 0; i < N; i++) {
                    WindowState w = mService.mWindows.get(i);
                    WindowStateAnimator winAnimator = mWinAnimators.get(i);
                    if (w.mIsWallpaper) {
                    if (winAnimator.mWin.mIsWallpaper) {
                        target = w;
                        target = winAnimator.mWin;
                        break;
                        break;
                    }
                    }
                }
                }
@@ -479,7 +531,9 @@ public class WindowAnimator {
        }
        }
    }
    }


    synchronized void animate() {
    // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */
    /** Locked on mService.mWindowMap and this. */
    private void animateLocked() {
        mPendingLayoutChanges = 0;
        mPendingLayoutChanges = 0;
        mCurrentTime = SystemClock.uptimeMillis();
        mCurrentTime = SystemClock.uptimeMillis();
        mBulkUpdateParams = 0;
        mBulkUpdateParams = 0;
@@ -546,7 +600,9 @@ public class WindowAnimator {
        }
        }


        if (mAnimating) {
        if (mAnimating) {
            mService.scheduleAnimationLocked();
            synchronized (mLayoutToAnim) {
                scheduleAnimationLocked();
            }
        } else if (wasAnimating) {
        } else if (wasAnimating) {
            mService.requestTraversalLocked();
            mService.requestTraversalLocked();
        }
        }
+31 −42
Original line number Original line Diff line number Diff line
@@ -655,33 +655,6 @@ public class WindowManagerService extends IWindowManager.Stub
    /** Only do a maximum of 6 repeated layouts. After that quit */
    /** Only do a maximum of 6 repeated layouts. After that quit */
    private int mLayoutRepeatCount;
    private int mLayoutRepeatCount;


    private final class AnimationRunnable implements Runnable {
        @Override
        public void run() {
            synchronized(mWindowMap) {
                mAnimationScheduled = false;
                // Update animations of all applications, including those
                // associated with exiting/removed apps
                synchronized (mAnimator) {
                    Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmAnimate");
                    final ArrayList<WindowStateAnimator> winAnimators = mAnimator.mWinAnimators;
                    winAnimators.clear();
                    final int N = mWindows.size();
                    for (int i = 0; i < N; i++) {
                        final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator;
                        if (winAnimator.mSurface != null) {
                            winAnimators.add(winAnimator);
                        }
                    }
                    mAnimator.animate();
                    Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                }
            }
        }
    }
    final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
    boolean mAnimationScheduled;

    final WindowAnimator mAnimator;
    final WindowAnimator mAnimator;


    final class DragInputEventReceiver extends InputEventReceiver {
    final class DragInputEventReceiver extends InputEventReceiver {
@@ -7151,7 +7124,11 @@ public class WindowManagerService extends IWindowManager.Stub


                case FORCE_GC: {
                case FORCE_GC: {
                    synchronized (mWindowMap) {
                    synchronized (mWindowMap) {
                        if (mAnimationScheduled) {
                        synchronized (mAnimator) {
                            // Since we're holding both mWindowMap and mAnimator we don't need to
                            // hold mAnimator.mLayoutToAnim.
                            if (mAnimator.mAnimating ||
                                    mAnimator.mLayoutToAnim.mAnimationScheduled) {
                                // If we are animating, don't do the gc now but
                                // If we are animating, don't do the gc now but
                                // delay a bit so we don't interrupt the animation.
                                // delay a bit so we don't interrupt the animation.
                                mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
                                mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
@@ -7164,6 +7141,7 @@ public class WindowManagerService extends IWindowManager.Stub
                                return;
                                return;
                            }
                            }
                        }
                        }
                    }
                    Runtime.getRuntime().gc();
                    Runtime.getRuntime().gc();
                    break;
                    break;
                }
                }
@@ -8955,9 +8933,20 @@ public class WindowManagerService extends IWindowManager.Stub
    }
    }


    void scheduleAnimationLocked() {
    void scheduleAnimationLocked() {
        if (!mAnimationScheduled) {
        final WindowAnimator.LayoutToAnimatorParams layoutToAnim = mAnimator.mLayoutToAnim;
            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationRunnable, null);
        synchronized (layoutToAnim) {
            mAnimationScheduled = true;
            // Copy local params to transfer params.
            ArrayList<WindowStateAnimator> winAnimators = layoutToAnim.mWinAnimators;
            winAnimators.clear();
            final int N = mWindows.size();
            for (int i = 0; i < N; i++) {
                final WindowStateAnimator winAnimator = mWindows.get(i).mWinAnimator;
                if (winAnimator.mSurface != null) {
                    winAnimators.add(winAnimator);
                }
            }
            layoutToAnim.mWallpaperTarget = mWallpaperTarget;
            mAnimator.scheduleAnimationLocked();
        }
        }
    }
    }