android.anim和android.anim.lf两个线程解析

背景:

在这里插入图片描述

在学员群中有学员朋友在分析systemserver的systrace和perfetto时候,提出了关于android.anim和android.anim.lf两个线程的相关疑问,主要是android.anim和android.anim.lf两个线程分别用于什么,有啥区别。针对这个疑问其实比较多学员朋友同样也想要知道答案,这里干脆写个文章来解答,分别日后学员朋友好查询,不需要挨个回答。

源码注释解答

首先看一下关于这里两个线程源码寻找方式:

test@test:~/aosp/frameworks/base$ grep "\"android.anim" ./ -rn | grep java
./tools/preload-check/src/com/android/preload/check/PreloadCheck.java:68:        run("com.android.preload.check.Initialized", "android.animation.Animator");
./services/core/java/com/android/server/AnimationThread.java:35:        super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
./services/core/java/com/android/server/wm/SurfaceAnimationThread.java:35:        super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);

可以看到./services/core/java/com/android/server/AnimationThread.java这个类就是代表的"android.anim"线程
./services/core/java/com/android/server/wm/SurfaceAnimationThread.java代表就是"android.anim.lf"线程
看看对应类的注释:

AnimationThread类

/**
 * Thread for handling all legacy window animations, or anything that's directly impacting
 * animations like starting windows or traversals.
 */
public final class AnimationThread extends ServiceThread {
    private static AnimationThread sInstance;
    private static Handler sHandler;

    private AnimationThread() {
        super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    }

注释说明:
AnimationThread主要用于处理一些遗留的窗口动画,货值其他直接会影响动画的,比如启动窗口,或者遍历树等

SurfaceAnimationThread类

/**
 * Thread for running {@link SurfaceAnimationRunner} that does not hold the window manager lock.
 */
public final class SurfaceAnimationThread extends ServiceThread {
    private static SurfaceAnimationThread sInstance;
    private static Handler sHandler;

    private SurfaceAnimationThread() {
        super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    }

注释说明:
这个其实就是新版本窗口动画流畅更新主要线程,也课程也讲解过的引入leash这种图层进行动画,不需要在持有 window manager lock的那一把大锁,可以直接对SurfaceControl的图层进行动画操作。所以更加流畅的核心就是不用再持有windowmanagerservice的大锁,所以独立出来了单独的动画线程来执行,减轻android.anim的负担

总结:
其实上面的注释也讲的比较清楚了,核心就是为了动画更加流畅,改进成了动画不需要在单独依赖windowmanagerservice的大锁,所以独立出来了一个单独的动画独立线程android.anim.lf。

这里可能学员朋友又有疑问,窗口动画都被搞到了线程android.anim.lf,那原来的线程android.anim岂不是架空了?android.anim还干些啥?
这个疑问同样AnimationThread的注释也已经说明了,主要干一些遗留窗口动画,还有启动窗口,遍历窗口等工作,具体也可以看一下相关的perfetto

android.anim的perfetto/systrace

trace可以看出android.anim会执行Traverser相关的任务
在这里插入图片描述

代码可以看这里

    void requestTraversal() {
        if (mTraversalScheduled) {
            return;
        }

        // Set as scheduled even the request will be deferred because mDeferredRequests is also
        // increased, then the end of deferring will perform the request.
        mTraversalScheduled = true;
        if (mDeferDepth > 0) {
            mDeferredRequests++;
            if (DEBUG) Slog.i(TAG, "Defer requestTraversal " + Debug.getCallers(3));
            return;
        }
        mService.mAnimationHandler.post(mPerformSurfacePlacement);
    }

当然也有很多地方会触发相关的animate,但是这个animate相关的活,和“动画”关系已经不那么大

可以看到这里的scheduleAnimation注释:

  /**
     * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
     * will be applied.
     */
    void scheduleAnimation() {
        if (mParent != null) {
            mParent.scheduleAnimation();
        }
    }

这里主要是来触发prepareSrufaces这个方法,让一些pending的事物进行apply

相关的animate方法如下:

private void animate(long frameTimeNs, long vsyncId) {
        scheduleAnimation();

        final RootWindowContainer root = mService.mRoot;
        mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
        mBulkUpdateParams = 0;
        root.mOrientationChangeComplete = true;
        if (DEBUG_WINDOW_TRACE) {
            Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
        }

        ProtoLog.i(WM_SHOW_TRANSACTIONS, ">>> OPEN TRANSACTION animate");
        mService.openSurfaceTransaction();
        try {
            // Remove all deferred displays, tasks, and activities.
            root.handleCompleteDeferredRemoval();

            final AccessibilityController accessibilityController =
                    mService.mAccessibilityController;
            final int numDisplays = mDisplayContentsAnimators.size();
            for (int i = 0; i < numDisplays; i++) {
                final int displayId = mDisplayContentsAnimators.keyAt(i);
                final DisplayContent dc = root.getDisplayContent(displayId);
                // Update animations of all applications, including those associated with
                // exiting/removed apps.
                dc.updateWindowsForAnimator();
                dc.prepareSurfaces();
            }

            for (int i = 0; i < numDisplays; i++) {
                final int displayId = mDisplayContentsAnimators.keyAt(i);
                final DisplayContent dc = root.getDisplayContent(displayId);

                dc.checkAppWindowsReadyToShow();
                if (accessibilityController.hasCallbacks()) {
                    accessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId,
                            mTransaction);
                }
            }

            cancelAnimation();

            if (mService.mWatermark != null) {
                mService.mWatermark.drawIfNeeded();
            }

        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        }

        final boolean hasPendingLayoutChanges = root.hasPendingLayoutChanges(this);
        final boolean doRequest = (mBulkUpdateParams != 0 || root.mOrientationChangeComplete)
                && root.copyAnimToLayoutParams();
        if (hasPendingLayoutChanges || doRequest) {
            mService.mWindowPlacerLocked.requestTraversal();
        }

        final boolean rootAnimating = root.isAnimating(TRANSITION | CHILDREN /* flags */,
                ANIMATION_TYPE_ALL /* typesToCheck */);
        if (rootAnimating && !mLastRootAnimating) {
            Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
        }
        if (!rootAnimating && mLastRootAnimating) {
            mService.mWindowPlacerLocked.requestTraversal();
            Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
        }
        mLastRootAnimating = rootAnimating;

        final boolean runningExpensiveAnimations =
                root.isAnimating(TRANSITION | CHILDREN /* flags */,
                        ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_SCREEN_ROTATION
                                | ANIMATION_TYPE_RECENTS /* typesToCheck */);
        if (runningExpensiveAnimations && !mRunningExpensiveAnimations) {
            // Usually app transitions put quite a load onto the system already (with all the things
            // happening in app), so pause task snapshot persisting to not increase the load.
            mService.mTaskSnapshotController.setPersisterPaused(true);
            mTransaction.setEarlyWakeupStart();
        } else if (!runningExpensiveAnimations && mRunningExpensiveAnimations) {
            mService.mTaskSnapshotController.setPersisterPaused(false);
            mTransaction.setEarlyWakeupEnd();
        }
        mRunningExpensiveAnimations = runningExpensiveAnimations;

        SurfaceControl.mergeToGlobalTransaction(mTransaction);
        mService.closeSurfaceTransaction("WindowAnimator");
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate");

        if (mRemoveReplacedWindows) {
            root.removeReplacedWindows();
            mRemoveReplacedWindows = false;
        }

        mService.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
        executeAfterPrepareSurfacesRunnables();
    }

相关的trace:
在这里插入图片描述

本文章更多详细代码和资料需要购买课程获取
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
在这里插入图片描述

私聊作者+v(androidframework007)

其他课程七件套专题:在这里插入图片描述
点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

视频试看:
https://www.bilibili.com/video/BV1wc41117L4/

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值