WMS动画原理

386 阅读2分钟

动画原理

动画本质上是,随着时间的流逝,施加不同的变化于窗口的 Surface.

AnimationSpec 接口,定义动画如何运行,包括运行时长、当前时间比例等,以及在不同的时间点上,通过事务施加不同的变形于Surface.

Animation 类提供起始值、结束值、插值器、Transformation 等;Transformation 包括 Matrix, Alpha.

public class WindowAnimationSpec implements AnimationSpec {
    // 定义起始值、结束值、运行时长、插值器等;
    private Animation mAnimation;
    
    @Override
    public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
        final TmpValues tmp = mThreadLocalTmps.get();
        tmp.transformation.clear();
        // 获取当前运行时间点的 Transformation
        mAnimation.getTransformation(currentPlayTime, tmp.transformation);        
        tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
        // 通过 Transaction 修改 Surface
        t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
        t.setAlpha(leash, tmp.transformation.getAlpha());
    }
}

SurfaceAnimationRunner 类驱动动画运行,以及提交Surface的事务。 SurfaceAnimationRunner 通过 ValueAnimator 驱动动画,ValueAnimator 内部包装 Choreograher 对象,请求下一帧的回调并继续运行动画。SurfaceAnimationRunner 类内部的 Choreograher 对象用于在下一帧的回调中提交事务。

class SurfaceAnimationRunner {

    private void startAnimationLocked(RunningAnimation a) {
        final ValueAnimator anim = mAnimatorFactory.makeAnimator();

        anim.setDuration(a.mAnimSpec.getDuration());
        anim.addUpdateListener(animation -> {
            synchronized (mCancelLock) {
                if (!a.mCancelled) {
                    final long duration = anim.getDuration();
                    long currentPlayTime = anim.getCurrentPlayTime();
                    if (currentPlayTime > duration) {
                        currentPlayTime = duration;
                    }
                    // 在每一帧中,调用 AnimationSpec 的 apply 方法
                    applyTransformation(a, mFrameTransaction, currentPlayTime);
                }
            }

            // 在下一帧使 Surface 的事务生效
            scheduleApplyTransaction();
        });

        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                synchronized (mCancelLock) {
                    if (!a.mCancelled) {
                        // 动画开始时,显示Surface
                        mFrameTransaction.setAlpha(a.mLeash, 1);
                    }
                }
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                synchronized (mLock) {
                    mRunningAnimations.remove(a.mLeash);
                    synchronized (mCancelLock) {
                        if (!a.mCancelled) {
                            mAnimationThreadHandler.post(a.mFinishCallback);
                        }
                    }
                }
            }
        });
        a.mAnim = anim;
        mRunningAnimations.put(a.mLeash, a);

        anim.start();
        ...
        // 立即开始动画
        anim.doAnimationFrame(mChoreographer.getFrameTime());
    }
    
    // 在 Choreograher 回调方法使 Transaction 生效
    private final Runnable mApplyTransactionRunnable = this::applyTransaction;
    
    private void applyTransaction() {
        mFrameTransaction.setAnimationTransaction();
        mFrameTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
        mFrameTransaction.apply();
        mApplyScheduled = false;
    }
}

SurfaceAnimator 创建和销毁 Leash, reparent 动画窗口的Surface. 并且作用动画于 Leash. AnimationAdapter 是 SurfaceAnimationRunner 与 AnimationSpec 之间的适配器。

    static SurfaceControl createAnimationLeash(Animatable animatable, SurfaceControl surface,
            Transaction t, @AnimationType int type, int width, int height, int x, int y,
            boolean hidden, Supplier<Transaction> transactionFactory) {
        // 1. 创建 Leash
        final SurfaceControl.Builder builder = animatable.makeAnimationLeash()
                .setParent(animatable.getAnimationLeashParent())
                .setName(surface + " - animation-leash of " + animationTypeToString(type))
                .setHidden(hidden)
                .setEffectLayer()
                .setCallsite("SurfaceAnimator.createAnimationLeash");
        final SurfaceControl leash = builder.build();
        // 2. 设置 Leash 的大小、位置、可见性;
        t.setWindowCrop(leash, width, height);
        t.setPosition(leash, x, y);
        t.show(leash);
        t.setAlpha(leash, hidden ? 0 : 1);
        // 3. 设置 Leash 为动画 Surface 的 parent
        t.reparent(surface, leash);
        return leash;
    }

开始动画时,创建Leash, 并在Surface层次结构中,使动画窗口的Surface reparent 到Leash上,作用动画于 Leash.

    void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
            @AnimationType int type,
            @Nullable OnAnimationFinishedCallback animationFinishedCallback,
            @Nullable Runnable animationCancelledCallback,
            @Nullable AnimationAdapter snapshotAnim, @Nullable SurfaceFreezer freezer) {
        cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
        mAnimation = anim;
        mAnimationType = type;
        mSurfaceAnimationFinishedCallback = animationFinishedCallback;
        mAnimationCancelledCallback = animationCancelledCallback;
        final SurfaceControl surface = mAnimatable.getSurfaceControl();
        ...
        // 1. 创建 Leash
        if (mLeash == null) {
            mLeash = createAnimationLeash(mAnimatable, surface, t, type,
                    mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
                    0 /* y */, hidden, mService.mTransactionFactory);
            mAnimatable.onAnimationLeashCreated(t, mLeash);
        }
        mAnimatable.onLeashAnimationStarting(t, mLeash);
        ...
        // 2. 开始动画
        mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
        ...
    }

在动画结束的回调中销毁 Leash, 并reparent窗口的Surface到原来的层次结构。


    private OnAnimationFinishedCallback getFinishedCallback(
            @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) {
        return (type, anim) -> {
            synchronized (mService.mGlobalLock) {
                ...
                final Runnable resetAndInvokeFinish = () -> {
                    ...
                    // 调用 removeLeash() 销毁 Leash
                    reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */);
                    ...
                };
                // 调用 resetAndInvokeFinish
                if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)
                        || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
                    resetAndInvokeFinish.run();
                }
                mAnimationFinished = true;
            }
        };
    }
    
    
    static boolean removeLeash(Transaction t, Animatable animatable, @NonNull SurfaceControl leash,
            boolean destroy) {
        boolean scheduleAnim = false;
        final SurfaceControl surface = animatable.getSurfaceControl();
        // 动画窗口的父窗口对应的Surface
        final SurfaceControl parent = animatable.getParentSurfaceControl();
        final SurfaceControl curAnimationLeash = animatable.getAnimationLeash();

        final boolean reparent = surface != null && (curAnimationLeash == null
                || curAnimationLeash.equals(leash));
        if (reparent) {
            if (surface.isValid() && parent != null && parent.isValid()) {
                // 恢复 Surface 的层级关系
                t.reparent(surface, parent);
                scheduleAnim = true;
            }
        }
        // 销毁 Leash
        if (destroy) {
            t.remove(leash);
            scheduleAnim = true;
        }
        ...
        return scheduleAnim;
    }