Android T 窗口动画(本地动画)显示流程其三——移除流程

359 阅读16分钟

动画移除流程

动画播放结束后回调函数分析

回调函数的调用过程

在动画播放流程中,SurfaceAnimationRunner.startAnimationLocked方法里,对动画结束通过onAnimationEnd方法进行了监听。

            @Override
            public void onAnimationEnd(Animator animation) {
                synchronized (mLock) {
                	//从mRunningAnimations这个映射(或字典)中移除与a.mLeash相关的动画。
                    mRunningAnimations.remove(a.mLeash);
                    synchronized (mCancelLock) {
                        if (!a.mCancelled) {

                            // Post on other thread that we can push final state without jank.
                            //调用回调函数
                            mAnimationThreadHandler.post(a.mFinishCallback);
                        }
                    }
                }
            }

mRunningAnimations.remove(a.mLeash);移除动画,后续mAnimationThreadHandler.post(a.mFinishCallback);回调函数。 其中传递的参数a.mFinishCallback,在RunningAnimation构造方法中对mFinishCallback进行了赋值。

        RunningAnimation(AnimationSpec animSpec, SurfaceControl leash, Runnable finishCallback) {
            mAnimSpec = animSpec;
            mLeash = leash;
            mFinishCallback = finishCallback;
        }

就是SurfaceAnimationRunner.startAnimation方法中的 final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash, finishCallback); 其中的finishCallback是从前面LocalAnimationAdapter.startAnimation方法中传递的() -> finishCallback.onAnimationFinished(type, this),调用这个函数开始动画的结束流程。

    @Override
    public void startAnimation(SurfaceControl animationLeash, Transaction t,
            @AnimationType int type, @NonNull OnAnimationFinishedCallback finishCallback) {
        mAnimator.startAnimation(mSpec, animationLeash, t,
                () -> finishCallback.onAnimationFinished(type, this));
    }

前面说了动画的播放流程,这里我们主要关注移除流程() -> finishCallback.onAnimationFinished(type, this)。 即a.mFinishCallback指的就是() -> finishCallback.onAnimationFinished(type, this)

回调函数的实现

onAnimationFinished(type, this)是OnAnimationFinishedCallback接口中的方法。 代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java

   /**
    * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
    * component that is running the animation when the animation is finished.
    */
   interface OnAnimationFinishedCallback {
       void onAnimationFinished(@AnimationType int type, AnimationAdapter anim);
   }

这是一个函数式接口,我们来看看这个接口是怎么实现的

finishCallback是OnAnimationFinishedCallback接口对象。结合前面SurfaceAnimator.startAnimation方法中调用的 mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);finishCallback的值就是mInnerAnimationFinishedCallback,这个参数同样是在SurfaceAnimator的构造方法中初始化的。

   /**
    * @param animatable The object to animate.
    * @param staticAnimationFinishedCallback Callback to invoke when an animation has finished
    *                                         running.
    */
   SurfaceAnimator(Animatable animatable,
           @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback,
           WindowManagerService service) {
       mAnimatable = animatable;
       mService = service;
       mStaticAnimationFinishedCallback = staticAnimationFinishedCallback;
       mInnerAnimationFinishedCallback = getFinishedCallback(staticAnimationFinishedCallback);
   }
  • 先来看看staticAnimationFinishedCallback 前面说过在WindowContainer构造方法中初始化 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms); 从代码中看staticAnimationFinishedCallback传递的是this::onAnimationFinished,onAnimationFinished在WindowContainer中实现 代码路径frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

       /**
        * Called when an animation has finished running.
        */
       protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
           ......
       }
    

    staticAnimationFinishedCallback.onAnimationFinished其实就是调用WindowContainer.onAnimationFinished方法

  • 再来看看mInnerAnimationFinishedCallback 其值是getFinishedCallback(staticAnimationFinishedCallback),即finishCallback实际上就是getFinishedCallback(staticAnimationFinishedCallback) 代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java

        private OnAnimationFinishedCallback getFinishedCallback(
                @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) {
            return (type, anim) -> {
                ......
            };
        }
    

    getFinishedCallback方法中实现了onAnimationFinished方法 () -> finishCallback.onAnimationFinished(type, this)onAnimationFinished(type, this)方法的实现,就是对应的是SurfaceAnimator.getFinishedCallback方法中的(type, anim) -> {......}

从上述代码中我们发现,如果回调参数的值是从WindowContainer传递过来的,那么就是是调用的WindowContainer.onAnimationFinished方法(如:this::onAnimationFinished对应的变量staticAnimationFinishedCallback调用的onAnimationFinished方法); 而在其他情况调用的onAnimationFinished方法,是调用SurfaceAnimator.getFinishedCallback方法中的(type, anim) -> {......}

下面我们来看看SurfaceAnimator.getFinishedCallback方法。

回调处理动画完成的逻辑

SurfaceAnimator.getFinishedCallback() 代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java

    private OnAnimationFinishedCallback getFinishedCallback(
            @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) {
        return (type, anim) -> {
            synchronized (mService.mGlobalLock) {
                //移除AnimationAdapter对应的SurfaceAnimator,并将这个SurfaceAnimator返回给target
                //mAnimationTransferMap属于启动窗口的动画场景,这里我们不涉及
                final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
                if (target != null) {
                    //递归调用onAnimationFinished(type, anim),即return (type, anim) -> {......}
                    //直到所有的SurfaceAnimator移除完
                    target.mInnerAnimationFinishedCallback.onAnimationFinished(type, anim);
                    return;
                }

                //检查动画是否已被新动画替换,如果当前动画 (anim) 不等于之前存储的动画 (mAnimation),则不执行后续操作
                if (anim != mAnimation) {
                    return;
                }
                //定义一个名为 resetAndInvokeFinish 的 Runnable
                final Runnable resetAndInvokeFinish = () -> {
                    // We need to check again if the animation has been replaced with a new
                    // animation because the animatable may defer to finish.
                    //再次检查动画是否已被新动画替换,因为可设置动画可能会延迟到完成。
                    if (anim != mAnimation) {
                        return;
                    }
                    //mSurfaceAnimationFinishedCallback是在WindowContainer.startAnimation中赋值的
                    //其传递值为null,最终SurfaceAnimator.startAnimation赋值给mSurfaceAnimationFinishedCallback
                    final OnAnimationFinishedCallback animationFinishCallback =
                            mSurfaceAnimationFinishedCallback;
                    //重置与动画相关的状态
                    reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */);
                    //WindowContainer构造方法中给SurfaceAnimator构造方法传递了staticAnimationFinishedCallback
                    if (staticAnimationFinishedCallback != null) {
                        //当一个Surface上的动画结束或取消且不重新启动时,这个回调将被执行。
                        //这是一个静态回调,它对通过这个 SurfaceAnimator 启动的所有动画都有效。
                        //回调WindowContainer.onAnimationFinished方法
                        staticAnimationFinishedCallback.onAnimationFinished(type, anim);
                    }
                    //mSurfaceAnimationFinishedCallback的值为null,因此animationFinishCallback的值为null
                    if (animationFinishCallback != null) {
                        //当一个Surface上的动画结束或取消且不重新启动时,这个回调将被执行。
                        //这个回调是每个动画(即每个 AnimationAdapter)特有的。
                        //如果在WindowContainer.startAnimation方法中有赋值,
                        //则回调WindowContainer.onAnimationFinished方法
                        animationFinishCallback.onAnimationFinished(type, anim);
                    }
                };
                // If both the Animatable and AnimationAdapter requests to be deferred, only the
                // first one will be called.
                //如果 mAnimatable 或动画本身请求延迟动画完成,并且它们都没有被延迟,
                //那么直接执行 resetAndInvokeFinish.run()。否则,延迟执行。
                if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)
                        || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
                    resetAndInvokeFinish.run();
                }
                //设置动画完成标志,将 mAnimationFinished 设置为 true
                mAnimationFinished = true;
            }
        };
    }

这个方法主要做了这几件事:

  1. 通过递归的方式移除所有AnimationAdapter对应的SurfaceAnimator 其中的mAnimationTransferMap在启动窗口流程中,ActivityRecord.addStartingWindow中有调用transferStartingWindow方法,逐步调用到SurfaceAnimator.transferAnimation中进行添加mService.mAnimationTransferMap.put(mAnimation, this);,这里我们不涉及,因此target的值为null
  2. 使用shouldDeferAnimationFinish方法(默认返回false)用来判断是否需要延迟完成动画
  3. 执行resetAndInvokeFinish.run(),调用reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */);重置动画相关状态
  4. 最后调用回调通过staticAnimationFinishedCallback.onAnimationFinished(type, anim);,调用WindowContainer.onAnimationFinished方法处理和响应动画完成的逻辑

重置动画相关状态并移除leash

reset(mAnimatable.getSyncTransaction(), true /* destroyLeash */); 代码路径:frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimator.java

    private void reset(Transaction t, boolean destroyLeash) {
        //移除AnimationAdapter对应的SurfaceAnimator
        mService.mAnimationTransferMap.remove(mAnimation);
        mAnimation = null;
        mSurfaceAnimationFinishedCallback = null;
        //动画类型置为空
        mAnimationType = ANIMATION_TYPE_NONE;
        //屏幕冻结时的快照
        final SurfaceFreezer.Snapshot snapshot = mSnapshot;
        mSnapshot = null;
        if (snapshot != null) {
            // Reset the mSnapshot reference before calling the callback to prevent circular reset.
            //如果有屏幕冻结时的快照,取消该动画。
            //最终会调用到SurfaceAnimationRunner.onAnimationCancelled
            snapshot.cancelAnimation(t, !destroyLeash);
        }
        if (mLeash == null) {
            return;
        }
        //使用leash存储动画图层mLeash
        SurfaceControl leash = mLeash;
        //把动画图层置为空
        mLeash = null;
        //移除leash
        final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
        //将mAnimationFinished设置为false
        mAnimationFinished = false;
        if (scheduleAnim) {
            //leash成功移除后,在WMS中会通过WindowAnimator调度动画,协调各个窗口
            mService.scheduleAnimationLocked();
        }
    }

移除leash

调用removeLeash方法移除leash final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash); 传递的mAnimatable表示当前窗口,leash就是动画图层,destroyLeash在前面getFinishedCallback流程中传递的值为true

    static boolean removeLeash(Transaction t, Animatable animatable, @NonNull SurfaceControl leash,
                               boolean destroy) {
        /* log add start*/
        Slog.i("WindowManager:","removeLeash leash = " + leash , new Exception());
        /* log add end*/
        //scheduleAnim一个标志位,初始值为false
        //为true时,走前面reset方法中的mService.scheduleAnimationLocked()流程
        boolean scheduleAnim = false;
        //获取当前窗口的SurfaceControl
        final SurfaceControl surface = animatable.getSurfaceControl();
        //获取当前窗口的父窗口的SurfaceControl
        final SurfaceControl parent = animatable.getParentSurfaceControl();
        //获取动画图层
        final SurfaceControl curAnimationLeash = animatable.getAnimationLeash();
        // If the surface was destroyed or the leash is invalid, we don't care to reparent it back.
        // Note that we also set this variable to true even if the parent isn't valid anymore, in
        // order to ensure onAnimationLeashLost still gets called in this case.
        // If the animation leash is set, and it is different from the removing leash, it means the
        // surface now has a new animation surface. We don't want to reparent for that.
        //1.surface不为空
        //2.curAnimationLeash不为空,且curAnimationLeash等于leash
        //因此reparent值为true
        final boolean reparent = surface != null && (curAnimationLeash == null
                || curAnimationLeash.equals(leash));
        if (reparent) {
            ProtoLog.i(WM_DEBUG_ANIM, "Reparenting to original parent: %s for %s",
                    parent, animatable);
            // We shouldn't really need these isValid checks but we do
            // b/130364451
            //判断当前窗口的surface是否有效,以及该窗口的父窗口的图层不为空且有效
            if (surface.isValid() && parent != null && parent.isValid()) {
                //把当前窗口图层和其父窗口的图层重新建立父子关系
                t.reparent(surface, parent);
                //scheduleAnim置为true
                scheduleAnim = true;
            }
        }
        //destroy传递过来值为true
        if (destroy) {
            //移除图层
            t.remove(leash);
            //scheduleAnim置为true
            scheduleAnim = true;
        }

        if (reparent) {
            // Make sure to inform the animatable after the surface was reparented (or reparent
            // wasn't possible, but we still need to invoke the callback)
            //1.移除和leash相关联的窗口和surface(这个只在前面requiresEdgeExtension为true时逻辑中有涉及)
            //2.调整surface
            animatable.onAnimationLeashLost(t);
            //scheduleAnim置为true
            scheduleAnim = true;
        }
        return scheduleAnim;
    }
  • 获取当前窗口的图层 final SurfaceControl surface = animatable.getSurfaceControl(); 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

        /**
         * @return The SurfaceControl for this container.
         *         The SurfaceControl must be valid if non-null.
         */
        @Override
        public SurfaceControl getSurfaceControl() {
            return mSurfaceControl;
        }
    

    直接返回一个SurfaceControl。

  • 获取当前窗口父窗口的图层 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

        /*
         * @return The SurfaceControl parent for this containers SurfaceControl.
         *         The SurfaceControl must be valid if non-null.
         */
        @Override
        public SurfaceControl getParentSurfaceControl() {
            final WindowContainer parent = getParent();
            if (parent == null) {
                return null;
            }
            return parent.getSurfaceControl();
        }
        
       @Override
       final protected WindowContainer getParent() {
           return mParent;
       }
    

    先获取当前窗口的父窗口,在获取父窗口的SurfaceControl。

  • 获取动画图层 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

    @Override
        public SurfaceControl getAnimationLeash() {
            return mAnimationLeash;
        }
    

    mAnimationLeash是前面SurfaceAnimator的startAnimation方法中的mAnimatable.onAnimationLeashCreated(t, mLeash);,把mLeash赋值给了mAnimationLeash,因此这个方法获取的是动画图层。

  • 当前窗口图层和其父窗口的图层重新建立父子关系 t.reparent(surface, parent); test-window的SurfaceControl重新认WindowToken的SurfaceControl为父。 代码路径:frameworks/base/core/java/android/view/SurfaceControl.java

            /**
             * Re-parents a given layer to a new parent. Children inherit transform (position, scaling)
             * crop, visibility, and Z-ordering from their parents, as if the children were pixels within the
             * parent Surface.
             *
             * @param sc The SurfaceControl to reparent
             * @param newParent The new parent for the given control.
             * @return This Transaction
             */
            @NonNull
            public Transaction reparent(@NonNull SurfaceControl sc,
                    @Nullable SurfaceControl newParent) {
                //检查传入的SurfaceControl对象是否满足某些预设条件
                checkPreconditions(sc);
                long otherObject = 0;
                if (newParent != null) {
                	//检查新父对象是否被释放。如果已经被释放,那么它会抛出异常。
                    newParent.checkNotReleased();
                    //新父对象不为null且未被释放,那么将新父对象的Native对象赋值给otherObject。
                    otherObject = newParent.mNativeObject;
                }
                //传入了三个参数:1.当前对象的Native对象 2.被重新设置父对象的SurfaceControl的Native对象 3.新父对象的Native对象。
                //用于实现重新设置父对象的具体操作。
                nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
                //把被重新设置父对象的SurfaceControl和新父对象存储到mReparentedSurfaces这个map中。
                mReparentedSurfaces.put(sc, newParent);
                return this;
            }
    

    前面说过reparent方法中通过mReparentedSurfaces这个ArrayMap临时存储父子关系,key值存储SurfaceControl对象,value为其父SurfaceControl对象,此时mReparentedSurfaces的键值对为: key:Surface(name=8aabddb test-window)/@0x1038e9a(当前窗口的SurfaceControl) value:Surface(name=WindowToken{15f96ea type=2038 android.os.BinderProxy@1d0fed5})/@0xc7312c1(当前窗口的父窗口的SurfaceControl,即WindowToken的SurfaceControl) 此时leash还没有被释放,WindowToken的SurfaceControl有两个儿子SurfaceControl,关系如下图所示: 在这里插入图片描述 此时leash逐渐发现不对劲,但是假装不知道 假如我们后面不执行移除leash图层的操作,那么这个图层一直会保持这个状态挂在WindowToken上和test-window共享父亲。

  • 移除动画图层 t.remove(leash);

            /**
             * Equivalent to reparent with a null parent, in that it removes
             * the SurfaceControl from the scene, but it also releases
             * the local resources (by calling {@link SurfaceControl#release})
             * after this method returns, {@link SurfaceControl#isValid} will return
             * false for the argument.
             *
             * @param sc The surface to remove and release.
             * @return This transaction
             * @hide
             */
            @NonNull
            public Transaction remove(@NonNull SurfaceControl sc) {
                reparent(sc, null);
                sc.release();
                return this;
            }
    

    同样调用了reparent方法,先把需要remove的图层的父图层置空,然后释放。 此时mReparentedSurfaces的键值对为: key:Surface(name=8aabddb test-window)/@0x1038e9a(当前窗口的SurfaceControl) value:Surface(name=WindowToken{15f96ea type=2038 android.os.BinderProxy@1d0fed5})/@0xc7312c1 (WindowToken的SurfaceControl) 和 key:Surface(name=Surface(name=8aabddb test-window)/@0x1038e9a - animation-leash of window_animation)/@0x38e37a8(动画图层leash) value:null 过程如下所示: 在这里插入图片描述 leash:原来我才是多余的那个,悠悠苍天,何薄于我!

  • 移除和leash相关联的窗口和surface并调整surface animatable.onAnimationLeashLost(t); 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

        @Override
        public void onAnimationLeashLost(Transaction t) {
            mLastLayer = -1;
            //调用mWmService中的mSurfaceAnimationRunner对象的onAnimationLeashLost方法
            //用于移除和leash相关联的窗口,这个只在前面requiresEdgeExtension为true时逻辑中有涉及
            mWmService.mSurfaceAnimationRunner.onAnimationLeashLost(mAnimationLeash, t);
            //mAnimationLeash置为空
            mAnimationLeash = null;
            mNeedsZBoost = false;
            //调整其所有child的z-order
            reassignLayer(t);
            //更新Surface位置
            updateSurfacePosition(t);
        }
    

    其中mWmService.mSurfaceAnimationRunner.onAnimationLeashLost(mAnimationLeash, t);mAnimationLeash前面说过就是动画图层。这个只在前面SurfaceAnimationRunner的startAnimation方法中requiresEdgeExtensiontrue时逻辑中有涉及,其为true时才会操作mEdgeExtensions这个ArrayList,这里不讨论。

协调动画显示

在SurfaceAnimator.reset()方法最后调用了mService.scheduleAnimationLocked(); 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    void scheduleAnimationLocked() {
        mAnimator.scheduleAnimation();
    }

    void scheduleAnimation() {
        if (!mAnimationFrameCallbackScheduled) {
            //mAnimationFrameCallbackScheduled 设置为 true,表示动画帧回调已经安排
            mAnimationFrameCallbackScheduled = true;
            //每一帧被绘制时,回调mAnimationFrameCallback
            mChoreographer.postFrameCallback(mAnimationFrameCallback);
        }
    }

和前面显示动画的流程一样有调用WindowAnimator的scheduleAnimation()方法,协调动画和窗口的显示。

处理和响应动画完成的逻辑

WindowContainer.onAnimationFinished方法 代码路径frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

   /**
    * Called when an animation has finished running.
    */
   protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
       //主要用于 清空 mSurfaceAnimationSources 列表
       doAnimationFinished(type, anim);
       //WindowManagerService中实现onAnimationFinished()
       //用于唤醒所有等待mGlobalLock对象的线程,确保多个线程能够正确地执行任务
       mWmService.onAnimationFinished();
       //将 mNeedsZBoost 设置为 false,表示不再需要Z轴增强
       mNeedsZBoost = false;
   }

	private void doAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
        for (int i = 0; i < mSurfaceAnimationSources.size(); ++i) {
            //mSurfaceAnimationSources中每个容器,做对应的onAnimationFinished
            mSurfaceAnimationSources.valueAt(i).onAnimationFinished(type, anim);
        }
        //清除动画源列表
        mSurfaceAnimationSources.clear();
        if (mDisplayContent != null) {
	        //调用DisplayContent的onWindowAnimationFinished方法
	        //从当前源码上看,主要是针对输入法相关做了一些操作
            mDisplayContent.onWindowAnimationFinished(this, type);
        }
    }

mSurfaceAnimationSources的值是在applyAnimationUnchecked方法中添加的,我们这里不属于远程动画流程,不涉及。 在ActivityRecord和WindowState中都重写了这个方法。我们这里是窗口动画,所以看看WindowState中的逻辑。

    @Override
    protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
        super.onAnimationFinished(type, anim);
        mWinAnimator.onAnimationFinished();
    }

先调用了父类前面WindowContainer中的onAnimationFinished,然后调用了WindowStateAnimator的onAnimationFinished方法。 代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java

	void onAnimationFinished() {
        // Done animating, clean up.
        ProtoLog.v(WM_DEBUG_ANIM, "Animation done in %s: exiting=%b, reportedVisible=%b",
                this, mWin.mAnimatingExit,
                (mWin.mActivityRecord != null && mWin.mActivityRecord.reportedVisible));

        //检查窗口可见性变化的flag
        mWin.checkPolicyVisibilityChange();
        final DisplayContent displayContent = mWin.getDisplayContent();
        //判断窗口类型为状态栏或通知栏的所有可见性标志位是否为true
        if ((mAttrType == LayoutParams.TYPE_STATUS_BAR
                || mAttrType == LayoutParams.TYPE_NOTIFICATION_SHADE) && mWin.isVisibleByPolicy()) {
            // Upon completion of a not-visible to visible status bar animation a relayout is
            // required.
            //设置mLayoutNeeded标志位为true
            displayContent.setLayoutNeeded();
        }
        //处理动画结束后窗口及其子窗口的状态更新和资源清理
        mWin.onExitAnimationDone();
        //将 displayContent 的 pendingLayoutChanges 标志设置为 FINISH_LAYOUT_REDO_ANIM
        displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
        //如果窗口是壁纸的目标
        if (displayContent.mWallpaperController.isWallpaperTarget(mWin)) {
            //将 pendingLayoutChanges 标志设置为 FINISH_LAYOUT_REDO_WALLPAPER
            displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
        }
        if (DEBUG_LAYOUT_REPEATS) {
            mService.mWindowPlacerLocked.debugLayoutRepeats(
                    "WindowStateAnimator", displayContent.pendingLayoutChanges);
        }

        if (mWin.mActivityRecord != null) {
            //更新窗口对应的应用的可见性
            mWin.mActivityRecord.updateReportedVisibilityLocked();
        }
    }

总结

至此动画从添加到移除的逻辑梳理完成,我们可以发现简单概括就起来动画的显示流程就是: 在窗口添加或移除时,添加动画,新增leash图层在当前窗口和其对应WindowToken之间,调整显示层级关系;播放完动画后,移除动画,移除leash图层,再次调整显示层级关系。

其他补充

SurfaceControl

Surface和SurfaceControl的关系是,Surface是图形生产者和图像消费之间传递数据的缓冲区,而SurfaceControl是Surface的控制类,可以实现复杂的Surface操作,如改变位置、缩放、剪切、透明度以及Z序等。所以当我们需要对某个Surface操作时,只需要修改其SurfaceControl即可。

代码位置:frameworks/base/core/java/android/view/SurfaceControl.java Surface相关的控制方法都在这里

创建图层

SurfaceControl.Builder的build()方法用于创建图层

	/**
     * Builder class for {@link SurfaceControl} objects.
     *
     * By default the surface will be hidden, and have "unset" bounds, meaning it can
     * be as large as the bounds of its parent if a buffer or child so requires.
     *
     * It is necessary to set at least a name via {@link Builder#setName}
     */
    public static class Builder {
        private SurfaceSession mSession;
        private int mFlags = HIDDEN;
        private int mWidth;
        private int mHeight;
        private int mFormat = PixelFormat.OPAQUE;
        private String mName;
        private WeakReference<View> mLocalOwnerView;
        private SurfaceControl mParent;
        private SparseIntArray mMetadata;
        private String mCallsite = "SurfaceControl.Builder";

        /**
         * Begin building a SurfaceControl with a given {@link SurfaceSession}.
         *
         * @param session The {@link SurfaceSession} with which to eventually construct the surface.
         * @hide
         */
        public Builder(SurfaceSession session) {
            mSession = session;
        }

        /**
         * Begin building a SurfaceControl.
         */
        public Builder() {
        }

        /**
         * Construct a new {@link SurfaceControl} with the set parameters. The builder
         * remains valid.
         */
        @NonNull
        public SurfaceControl build() {
            if (mWidth < 0 || mHeight < 0) {
                throw new IllegalStateException(
                        "width and height must be positive or unset");
            }
            if ((mWidth > 0 || mHeight > 0) && (isEffectLayer() || isContainerLayer())) {
                throw new IllegalStateException(
                        "Only buffer layers can set a valid buffer size.");
            }

            if ((mFlags & FX_SURFACE_MASK) == FX_SURFACE_NORMAL) {
                setBLASTLayer();
            }

            return new SurfaceControl(
                    mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
                    mLocalOwnerView, mCallsite);
        }
        ......
    }

移除图层

SurfaceControl.Transaction的remove()方法用于移除图层

    /**
     * An atomic set of changes to a set of SurfaceControl.
     */
    public static class Transaction implements Closeable, Parcelable {
    ......
		/**
         * Equivalent to reparent with a null parent, in that it removes
         * the SurfaceControl from the scene, but it also releases
         * the local resources (by calling {@link SurfaceControl#release})
         * after this method returns, {@link SurfaceControl#isValid} will return
         * false for the argument.
         *
         * @param sc The surface to remove and release.
         * @return This transaction
         * @hide
         */
        @NonNull
        public Transaction remove(@NonNull SurfaceControl sc) {
            reparent(sc, null);
            sc.release();
            return this;
        }
    ......
    }

修改图层父子关系

SurfaceControl.Transaction的reparent()方法用于修改图层父子关系

        /**
         * Re-parents a given layer to a new parent. Children inherit transform (position, scaling)
         * crop, visibility, and Z-ordering from their parents, as if the children were pixels within the
         * parent Surface.
         *
         * @param sc The SurfaceControl to reparent
         * @param newParent The new parent for the given control.
         * @return This Transaction
         */
        @NonNull
        public Transaction reparent(@NonNull SurfaceControl sc,
                @Nullable SurfaceControl newParent) {
            //检查传入的SurfaceControl对象是否满足某些预设条件
            checkPreconditions(sc);
            long otherObject = 0;
            if (newParent != null) {
            	//检查新父对象是否被释放。如果已经被释放,那么它会抛出异常。
                newParent.checkNotReleased();
                //新父对象不为null且未被释放,那么将新父对象的Native对象赋值给otherObject。
                otherObject = newParent.mNativeObject;
            }
            //传入了三个参数:1.当前对象的Native对象 2.被重新设置父对象的SurfaceControl的Native对象 3.新父对象的Native对象。
            //用于实现重新设置父对象的具体操作。
            nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
            //把被重新设置父对象的SurfaceControl和新父对象存储到mReparentedSurfaces这个map中。
            mReparentedSurfaces.put(sc, newParent);
            return this;
        }

简单聊聊Choreographer

Choreographer扮演 Android 渲染链路中承上启下的角色 承上:负责接收和处理 App 的各种更新消息和回调,等到 Vsync(垂直同步) 到来的时候统一处理。比如集中处理 Input(主要是 Input 事件的处理) 、Animation(动画相关)、Traversal(包括 measure、layout、draw 等操作) ,判断卡顿掉帧情况,记录 CallBack 耗时等 启下:负责请求和接收 Vsync 信号。接收 Vsync 事件回调(通过 FrameDisplayEventReceiver.onVsync );请求 Vsync(FrameDisplayEventReceiver.scheduleVsync) 我们这里mChoreographer.postFrameCallback(this::startAnimations);其实就是先请求Vsync信号,然后接收到Vsync信号回调this::startAnimations

Choreographer的postFrameCallback和postCallback在处理方式和使用场景上有所不同。

Choreographer的postFrameCallback主要用于在下一个frame渲染时控制执行某些操作,例如View的绘制流程。这个方法会在下一个Vsync信号来临时,遍历CallbackQuenes中的链表,并执行对应的回调方法。这个方法主要在ViewRootImpl中使用,用于分发处理NativeInputQueue的消息回调。

而Choreographer的postCallback则是一个更通用的回调方法,它允许在UI线程中安排一个回调。这个方法可以接受Runnable对象作为参数,该对象定义了回调时要执行的任务。postCallback方法可以在任何需要延迟执行任务或异步处理任务的情况下使用,而不仅仅是在渲染帧时。

总的来说,postFrameCallback更专注于在特定时间点(如渲染帧时)执行特定任务,而postCallback则提供了一种更通用的方式来安排回调,可以在任何需要的时候使用。