屏幕的刷新率一般为60fps,当然最新的手机刷新率更高,这一切都是surfacelinger的安排,通过一个叫Choreographer来监控和保证应用的帧率为固定的1/60s。

1choreographer概述

我们直接看源码中的翻译解释

用于协调动画、输入和绘图的时间。编舞者从显示子系统接收定时脉冲(例如垂直同步),然后安排工作作为渲染下一显示帧的一部分。应用程序通常使用动画框架或视图层次结构中的更高级别抽象间接与编舞者交互。以下是您可以使用更高级别 API 执行的操作的一些示例。

  1. 要定期显示要与显示帧渲染同步处理的动画,请使用 {@link android.animation.ValueAnimator#start}。
  2. 要显示{@link Runnable} 以在下一个显示帧开始时调用一次,请使用 {@link View#postOnAnimation}
  3. 要显示{@link Runnable} 以在延迟后的下一个显示帧开始时调用一次,请使用 {@link View#postOnAnimationDelayed}
  4. 要在下一个显示帧开始时发布一次对 {@link View#invalidate()} 的调用,请使用 {@link View#postInvalidateOnAnimation()} 或 {@link View#postInvalidateOnAnimation(int,int, int, int)}。
  5. 如果您的应用程序在不同的线程中进行渲染,可能使用 GL,或者根本不使用动画框架或视图层次结构,并且您希望确保它与显示适当同步,则使用 {@link choreography#postFrameCallback}。每个 {@link Looper} 线程都有自己的choreographer。其他线程可以发布回调以在编排器上运行,但它们将在编排器所属的 {@link Looper} 上运行。

关于上面的几点现在看会有点懵,笔者这里先按下不表,继续往下看。

1.1choreography由来

界面的显示大体会经过CPU的计算-> GPU合成栅格化->显示设备显示。我们知道Android设备的刷新频率一般都是60HZ也就是一秒60次,如果一次绘制在约16毫喵内完成时没有问题的。但是一旦出现不协调的地方就会出问题如下图

  • 第一个周期,cpu计算、GPU操作、显示设备显示没有问题。
  • 第二个周期,显示上一个周期绘制准备好的图像;CPU计算是在周期将要结束的时候才开始计算
  • 第三个周期,由于进入第二个周期的时候CPU动手计算晚点了,致使进入第三个周期的时候本应该显示的图像没有准备好,导致整个第三个周期内还是显示上一个周期的图像,这样看上去会卡,掉帧!google工程师们管整个叫Jank延误军机。

垂直同步简单的说,就是让CPU计算别没有计划没有规律而是在每个周期开始的时候开始计算,这样就有条不紊的有序进行了(如下图)。因此在android4.1及以后的版本中加入了Choreographer这个类,Choreographer收到VSync信号才开始绘制,保证绘制拥有完整的16.7ms,避免绘制的随机性。

1.2choreography作用

这个原理可以简单的理解为是Handler的消息机制的变体。只不过这里用到了更多的异步消息的同步屏障处理。

Choreographer 的引入,主要是配合 Vsync ,给上层 App 的渲染提供一个稳定的 Message 处理的时机,也就是 Vsync 到来的时候 ,系统通过对 Vsync 信号周期的调整,来控制每一帧绘制操作的时机. 至于为什么 Vsync 周期选择是 16.7ms (60 fps) ,是因为目前大部分手机的屏幕都是 60Hz 的刷新率,也就是 16.7ms 刷新一次,系统为了配合屏幕的刷新频率,将 Vsync 的周期也设置为 16.7 ms,每隔 16.7 ms ,Vsync 信号到来唤醒 Choreographer 来做 App 的绘制操作 ,如果每个 Vsync 周期应用都能渲染完成,那么应用的 fps 就是 60 ,给用户的感觉就是非常流畅,这就是引入 Choreographer 的主要作用。

2源码分析

本文主要结合android11的源码分析。

2.1Choreographer 的初始化

首先是choreographyer的启动。在Activity启动过程,执行完onResume后,会调用Activity.makeVisible(),然后再调用到addView(), 层层调用会进入如下方法

1//frameworks/base/core/java/android/view/ViewRootImpl.java#ViewRootImpl
2public ViewRootImpl(Context context, Display display, IWindowSession session,
3                    boolean useSfChoreographer) {
4    ...
5    //开始初始化mChoreographer,默认的传入的useSfChoreographer都为false
6    mChoreographer = useSfChoreographer
7        ? Choreographer.getSfInstance() : Choreographer.getInstance();
8    ...
9}

从ViewRootImpl.java开始构造Choreographer。当前所在线程为UI线程,也就是常说的主线程。但是实际上UI也可以在子线程更新,所以这里有一个是否为主线程的looper判断。

 1//frameworks/base/core/java/android/view/Choreographer.java#getInstance
 2public static Choreographer getInstance() {
 3    return sThreadInstance.get();
 4}
 5
 6//通过Threadlocal来获取choreographer的单例,标记为VSYNC_SOURCE_APP
 7//useSfChoreographer传入的值为true的时候,标记为VSYNC_SOURCE_SURFACE_FLINGER
 8private static final ThreadLocal<Choreographer> sThreadInstance =
 9    new ThreadLocal<Choreographer>() {
10    @Override
11    protected Choreographer initialValue() {
12        //获取当前线程的looper
13        Looper looper = Looper.myLooper();
14        if (looper == null) {
15            throw new IllegalStateException("The current thread must have a looper!");
16        }
17        Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
18        //通常looper都是主线程的looper,但也存在子线程更新UI的情况
19        if (looper == Looper.getMainLooper()) {
20            mMainInstance = choreographer;
21        }
22        return choreographer;
23    }
24};

2.1.1Choreographer单例构造

这个Choreographer最重要的三个实例化的属性,mHandler,mDisplayEventReceiver和mCallbackQueues

 1//frameworks/base/core/java/android/view/Choreographer.java#Choreographer
 2private static final boolean USE_VSYNC = SystemProperties.getBoolean(
 3    "debug.choreographer.vsync", true);
 4
 5private Choreographer(Looper looper, int vsyncSource) {
 6    mLooper = looper;
 7    //[2.1.2]
 8    mHandler = new FrameHandler(looper);
 9    //这里的USE_VSYNC默认就是开启的,除非手动通过设置属性将Choreographer关闭。
10    //关闭方式setprop debug.choreographer.vsync false
11    //[2.1.3]
12    mDisplayEventReceiver = USE_VSYNC
13        ? new FrameDisplayEventReceiver(looper, vsyncSource)
14        : null;
15    mLastFrameTimeNanos = Long.MIN_VALUE;
16
17    mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
18    //[2.1.4]
19    mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
20    for (int i = 0; i <= CALLBACK_LAST; i++) {
21        mCallbackQueues[i] = new CallbackQueue();
22    }
23    // b/68769804: For low FPS experiments.
24    setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
25}
  • mLastFrameTimeNanos:是指上一次帧绘制时间点;
  • mFrameIntervalNanos:帧间时长,一般等于16.7ms.

2.1.2mHandler

 1//frameworks/base/core/java/android/view/Choreographer.java#FrameHandler
 2mHandler = new FrameHandler(looper);
 3
 4//实际上就是内部的一个Handler,用于处理内部事件,这里的事件分成三项
 5//FrameHandler的事件
 6//MSG_DO_FRAME
 7//MSG_DO_SCHEDULE_VSYNC
 8//MSG_DO_SCHEDULE_CALLBACK
 9private final class FrameHandler extends Handler {
10    public FrameHandler(Looper looper) {
11        //初始化handler
12        super(looper);
13    }
14
15    @Override
16    public void handleMessage(Message msg) {
17        switch (msg.what) {
18            case MSG_DO_FRAME:
19                doFrame(System.nanoTime(), 0);
20                break;
21            case MSG_DO_SCHEDULE_VSYNC:
22                doScheduleVsync();
23                break;
24            case MSG_DO_SCHEDULE_CALLBACK:
25                doScheduleCallback(msg.arg1);
26                break;
27        }
28    }
29}

2.1.3mDisplayEventReceiver

这个可以看到里面有几个属性,分别为mHavePendingVsync,mTimestampNanos和mFrame,另外有两个回调onVsync和run。具体在后面展开关于DisplayEventReceiver描述。

 1//frameworks/base/core/java/android/view/Choreographer.java#FrameDisplayEventReceiver
 2//这里的vsyncSource为VSYNC_SOURCE_APP或者为VSYNC_SOURCE_SURFACE_FLINGER
 3mDisplayEventReceiver = new FrameDisplayEventReceiver(looper, vsyncSource);
 4
 5private final class FrameDisplayEventReceiver extends DisplayEventReceiver
 6    implements Runnable {
 7    private boolean mHavePendingVsync;
 8    private long mTimestampNanos;
 9    private int mFrame;
10
11    //【见小节2.2Choreographer中Vsync的注册】
12    public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
13        super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS);
14    }
15
16    @Override
17    public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
18        long now = System.nanoTime();
19        if (timestampNanos > now) {
20            Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
21                  + " ms in the future!  Check that graphics HAL is generating vsync "
22                  + "timestamps using the correct timebase.");
23            timestampNanos = now;
24        }
25
26        if (mHavePendingVsync) {
27            Log.w(TAG, "Already have a pending vsync event.  There should only be "
28                  + "one at a time.");
29        } else {
30            mHavePendingVsync = true;
31        }
32
33        mTimestampNanos = timestampNanos;
34        mFrame = frame;
35        Message msg = Message.obtain(mHandler, this);
36        msg.setAsynchronous(true);
37        mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
38    }
39
40    @Override
41    public void run() {
42        mHavePendingVsync = false;
43        doFrame(mTimestampNanos, mFrame);
44    }
45}

2.1.4mCallbackQueues

这个是一个数据结构为CallbackQueue类型的数组,元素大小为5,分别代表CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_INSETS_ANIMATION、CALLBACK_TRAVERSAL和CALLBACK_COMMIT。每个元素都有CallbackRecord类型的按时间戳排列的优先级队列mHead。

mCallbackQueues数据结构图,可以通过下面代码可知是按时间的优先级排序的链表队列

1)提取extractDueCallbacksLocked

此方法就是为了得到执行时间小于当前时间的Callback链表集合,得到之后会将链表断成两份,前面一份为需要马上执行的Callback,后面一份为还未到执行时间的Callback,这样保证了下一次绘制请求的Callback能够放在后面一个链表中,最早也在下一个Vsync到才执行

2)插入addCallbackLocked

3)消费removeCallbacksLocked

  1//frameworks/base/core/java/android/view/Choreographer.java#FrameDisplayEventReceiver
  2public static final int CALLBACK_INPUT = 0;
  3public static final int CALLBACK_ANIMATION = 1;
  4public static final int CALLBACK_INSETS_ANIMATION = 2;
  5public static final int CALLBACK_TRAVERSAL = 3;
  6public static final int CALLBACK_COMMIT = 4;
  7private static final int CALLBACK_LAST = CALLBACK_COMMIT;
  8
  9mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
 10
 11//CallbackRecord是一个数据类型,主要用于存储三个属性,dueTime,action和token
 12//action为Runnable或者 FrameCallback两者的子类
 13//token会在后面体现出来,主要是用于区分两个api的调用,分别为FRAME_CALLBACK_TOKEN和其他,
 14//其中postFrameCallback调用的api定义token为FRAME_CALLBACK_TOKEN
 15//其中postCallback调用的api定义token为其他
 16private static final class CallbackRecord {
 17    public CallbackRecord next;
 18    public long dueTime;
 19    public Object action; // Runnable or FrameCallback
 20    public Object token;
 21
 22    @UnsupportedAppUsage
 23    public void run(long frameTimeNanos) {
 24        if (token == FRAME_CALLBACK_TOKEN) {
 25            ((FrameCallback)action).doFrame(frameTimeNanos);
 26        } else {
 27            ((Runnable)action).run();
 28        }
 29    }
 30}
 31
 32private final class CallbackQueue {
 33    //单个元素内部有一个CallbackRecord类型的mHead队列
 34    private CallbackRecord mHead;
 35
 36    public boolean hasDueCallbacksLocked(long now) {
 37        return mHead != null && mHead.dueTime <= now;
 38    }
 39    //将对应元素中维护的mHead队列元素取出来
 40    //将小于等于传入时间戳的mHead队列元素取出来
 41    public CallbackRecord extractDueCallbacksLocked(long now) {
 42        CallbackRecord callbacks = mHead;
 43        //如果将元素取出来消费,必须使得mHead队列头部的时间要早于需要时间
 44        if (callbacks == null || callbacks.dueTime > now) {
 45            return null;
 46        }
 47
 48        CallbackRecord last = callbacks;
 49        CallbackRecord next = last.next;
 50        while (next != null) {
 51            if (next.dueTime > now) {
 52                last.next = null;
 53                break;
 54            }
 55            last = next;
 56            next = next.next;
 57        }
 58        mHead = next;
 59        return callbacks;
 60    }
 61
 62    //按照元素种类添加对应的内部mHead队列元素
 63    public void addCallbackLocked(long dueTime, Object action, Object token) {
 64        CallbackRecord callback = obtainCallbackLocked(dueTime, action, token);
 65        CallbackRecord entry = mHead;
 66        //如果之前没有mHead队列,那么传入的单个元素callback就为新的mHead队列的队头
 67        if (entry == null) {
 68            mHead = callback;
 69            return;
 70        }
 71        //将单个元素callback插入到mHead队列前面
 72        if (dueTime < entry.dueTime) {
 73            callback.next = entry;
 74            mHead = callback;
 75            return;
 76        }
 77        //将单个元素callback按照时间优先级插入到mHead队列中
 78        while (entry.next != null) {
 79            if (dueTime < entry.next.dueTime) {
 80                callback.next = entry.next;
 81                break;
 82            }
 83            entry = entry.next;
 84        }
 85        entry.next = callback;
 86    }
 87
 88    //去除对应mHead对应action和token的CallbackRecord元素
 89    public void removeCallbacksLocked(Object action, Object token) {
 90        CallbackRecord predecessor = null;
 91        for (CallbackRecord callback = mHead; callback != null;) {
 92            final CallbackRecord next = callback.next;
 93            if ((action == null || callback.action == action)
 94                && (token == null || callback.token == token)) {
 95                if (predecessor != null) {
 96                    predecessor.next = next;
 97                } else {
 98                    mHead = next;
 99                }
100                recycleCallbackLocked(callback);
101            } else {
102                predecessor = callback;
103            }
104            callback = next;
105        }
106    }
107}

2.2Choreographer中Vsync的注册

承接上述的[2.1.3],主要是对DisplayEventReceiver进行一个初始化,并且对Vysnc信号进行一个注册

2.2.1DisplayEventReceiver的构造

 1//frameworks/base/core/java/android/view/DisplayEventReceiver.java#DisplayEventReceiver
 2public DisplayEventReceiver(Looper looper, int vsyncSource, int configChanged) {
 3    if (looper == null) {
 4        throw new IllegalArgumentException("looper must not be null");
 5    }
 6
 7    mMessageQueue = looper.getQueue();
 8    //[2.2.2]
 9    mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
10            vsyncSource, configChanged);
11
12    mCloseGuard.open("dispose");
13}

2.2.2nativeInit

 1//frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp#nativeInit
 2static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
 3        jobject messageQueueObj, jint vsyncSource, jint configChanged) {
 4    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
 5    ...
 6    //[2.2.3]
 7    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
 8            receiverWeak, messageQueue, vsyncSource, configChanged);
 9    //[2.2.5]
10    status_t status = receiver->initialize();
11
12    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
13    return reinterpret_cast<jlong>(receiver.get());
14}

2.2.3NativeDisplayEventReceiver

 1//frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp#NativeDisplayEventReceiver
 2NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
 3        jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource,
 4        jint configChanged) :
 5        DisplayEventDispatcher(messageQueue->getLooper(),
 6                static_cast<ISurfaceComposer::VsyncSource>(vsyncSource),
 7                static_cast<ISurfaceComposer::ConfigChanged>(configChanged)),
 8        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
 9        mMessageQueue(messageQueue) {
10    ALOGV("receiver %p ~ Initializing display event receiver.", this);
11}

在初始化NativeDisplayEventReceiver的同时,由于也初始化了基类的构造

1//frameworks/native/libs/gui/DisplayEventDispatcher.cpp#DisplayEventDispatcher
2DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
3                                               ISurfaceComposer::VsyncSource vsyncSource,
4                                               ISurfaceComposer::ConfigChanged configChanged)
5        //初始化mLooper,mReceiver和类成员变量mWaitingForVsync,这个值在后续的processPendingEvents会用到
6        //mReceiver的初始化[2.2.4]
7      : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) {
8    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
9}

2.2.4mReceiver初始化

这里面的逻辑比较清晰,首先是sf的构造,其次是mEventConnection的初始化,最后是mEventConnection的stealReceiveChannel

 1//frameworks/native/libs/gui/DisplayEventReceiver.cpp#DisplayEventReceiver
 2DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource,
 3                                           ISurfaceComposer::ConfigChanged configChanged) {
 4    //这里有两个一个是获取Composer服务,一个是sf的构造
 5    //ComposerService::getComposerService(),[2.2.4.1]
 6    //sf的构造,[2.2.4.3]
 7    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
 8    if (sf != nullptr) {
 9        //[2.2.4.4]
10        mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged);
11        if (mEventConnection != nullptr) {
12            //获取到一个BitTube的智能指针变量mDataChannel
13            mDataChannel = std::make_unique<gui::BitTube>();
14            //[2.2.4.12]
15            mEventConnection->stealReceiveChannel(mDataChannel.get());
16        }
17    }
18}

2.2.4.1getComposerService

getComposerService函数定义在ComposerService.h头文件中,内部持有ISurfaceComposer的成员变量

 1//frameworks/native/libs/gui/include/private/gui/ComposerService.h#ComposerService
 2class ISurfaceComposer;
 3
 4class ComposerService : public Singleton<ComposerService>
 5{
 6    sp<ISurfaceComposer> mComposerService;
 7    sp<IBinder::DeathRecipient> mDeathObserver;
 8    Mutex mLock;
 9
10    ComposerService();
11    void connectLocked();
12    void composerServiceDied();
13    friend class Singleton<ComposerService>;
14public:
15    static sp<ISurfaceComposer> getComposerService();
16};

这里获取的ComposerService是一个单例

 1//frameworks/native/libs/gui/SurfaceComposerClient.cpp#getComposerService
 2/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
 3    ComposerService& instance = ComposerService::getInstance();
 4    Mutex::Autolock _l(instance.mLock);
 5    if (instance.mComposerService == nullptr) {
 6        //这里有一个服务获取[2.2.4.2]
 7        ComposerService::getInstance().connectLocked();
 8        assert(instance.mComposerService != nullptr);
 9        ALOGD("ComposerService reconnected");
10    }
11    return instance.mComposerService;
12}

2.2.4.2connectLocked

获取链接的远端服务,这里可以看出通过ServiceManager来获取对应服务,这个服务是SurfaceFlinger,并且设置了对应的死亡回调

在SurfaceFlinger服务初始化的时候,就会把对应的name添加到ServiceManager中,所有后续能够直接通过getService中的名字直接获取到对应的服务。

 1//frameworks/native/libs/gui/SurfaceComposerClient.cpp#connectLocked
 2void ComposerService::connectLocked() {
 3    const String16 name("SurfaceFlinger");
 4    while (getService(name, &mComposerService) != NO_ERROR) {
 5        usleep(250000);
 6    }
 7    assert(mComposerService != nullptr);
 8
 9    //设置死亡回调
10    class DeathObserver : public IBinder::DeathRecipient {
11        ComposerService& mComposerService;
12        virtual void binderDied(const wp<IBinder>& who) {
13            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
14                  who.unsafe_get());
15            mComposerService.composerServiceDied();
16        }
17     public:
18        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
19    };
20
21    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
22    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
23}

2.2.4.3sf的构造

这里有一个显示的构造,实际上是传入的就是impl,这里的impl就是上面getservice获取到的SurfaceFlinger实例。关于explicit关键字,可以点击这里

 1//frameworks/native/libs/gui/ISurfaceComposer.cpp#BpSurfaceComposer#BpSurfaceComposer
 2class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
 3{
 4public:
 5    explicit BpSurfaceComposer(const sp<IBinder>& impl)
 6        : BpInterface<ISurfaceComposer>(impl)
 7    {
 8    }
 9    ...
10};

2.2.4.4createDisplayEventConnection

 1//frameworks/native/libs/gui/ISurfaceComposer.cpp#BpSurfaceComposer#createDisplayEventConnection
 2class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
 3{
 4    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource,
 5                                                                     ConfigChanged configChanged) {
 6        Parcel data, reply;
 7        sp<IDisplayEventConnection> result;
 8        int err = data.writeInterfaceToken(
 9            ISurfaceComposer::getInterfaceDescriptor());
10        if (err != NO_ERROR) {
11            return result;
12        }
13        data.writeInt32(static_cast<int32_t>(vsyncSource));
14        data.writeInt32(static_cast<int32_t>(configChanged));
15        //开始进行binder操作,操作内容为CREATE_DISPLAY_EVENT_CONNECTION,[2.2.4.5]
16        err = remote()->transact(
17            BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
18            data, &reply);
19        if (err != NO_ERROR) {
20            ALOGE("ISurfaceComposer::createDisplayEventConnection: error performing "
21                  "transaction: %s (%d)", strerror(-err), -err);
22            return result;
23        }
24        result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
25        return result;
26    }
27};

2.2.4.5transact

通过binder通信,会调到ontrasact

 1//frameworks/native/libs/gui/ISurfaceComposer.cpp#BnSurfaceComposer#onTransact
 2status_t BnSurfaceComposer::onTransact(
 3    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 4{
 5    switch(code) {
 6         ...
 7         case CREATE_DISPLAY_EVENT_CONNECTION: {
 8            CHECK_INTERFACE(ISurfaceComposer, data, reply);
 9            auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
10            auto configChanged = static_cast<ISurfaceComposer::ConfigChanged>(data.readInt32());
11            //其实这边还比较复杂,用一次用到了binder,这里的connection也是IDisplayEventConnection初始化
12            //createDisplayEventConnection,[2.2.4.6]
13            //connection,[2.2.4.11]
14            sp<IDisplayEventConnection> connection(
15                    createDisplayEventConnection(vsyncSource, configChanged));
16            reply->writeStrongBinder(IInterface::asBinder(connection));
17            return NO_ERROR;
18        }
19        ...
20    }
21}

可以得知目前传入的值,vsyncSource值为eVsyncSourceApp,configChanged值为CONFIG_CHANGED_EVENT_SUPPRESS

1//frameworks/native/libs/gui/include/gui/ISurfaceComposer.h
2enum VsyncSource {
3    eVsyncSourceApp = 0,
4    eVsyncSourceSurfaceFlinger = 1
5};
6
7enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 };

2.2.4.6createDisplayEventConnection

由于直到服务端是SurfaceFlinger,即SurfaceFlinger是继承BnSurfaceComposer的,所以最终调用到SurfaceFlinger中,这个函数主要是为了初始化EventThreadConnection

1//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp#createDisplayEventConnection
2sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
3        ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
4    const auto& handle =
5            vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
6    //[2.2.4.7]
7    return mScheduler->createDisplayEventConnection(handle, configChanged);
8}

2.2.4.7createDisplayEventConnection

通过Scheduler来管理EventThreadConnection和EventThread的实例

1//frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp#createDisplayEventConnection
2sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
3        ConnectionHandle handle, ISurfaceComposer::ConfigChanged configChanged) {
4    RETURN_IF_INVALID_HANDLE(handle, nullptr);
5    //[2.2.4.8]
6    return createConnectionInternal(mConnections[handle].thread.get(), configChanged);
7}

这里的mConnections是在头文件Scheduler.h中定义的

 1//frameworks/native/services/surfaceflinger/Scheduler/Scheduler.h#Scheduler
 2class Scheduler : public IPhaseOffsetControl {
 3    ...
 4    struct Connection {
 5        sp<EventThreadConnection> connection;
 6        std::unique_ptr<EventThread> thread;
 7    };
 8	std::unordered_map<ConnectionHandle, Connection> mConnections;
 9    ...
10};

2.2.4.8createConnectionInternal

1//frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp#createConnectionInternal
2sp<EventThreadConnection> Scheduler::createConnectionInternal(
3        EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) {
4    //[2.2.4.9]
5    return eventThread->createEventConnection([&] { resync(); }, configChanged);
6}

2.2.4.9eventThread->createEventConnection

最终调用到eventThread->createEventConnection,这里还是用了内部匿名方式,用于初始化EventThreadConnection,其中这里的this指的是SurfaceFinger初始化EventThread的实例,对于EventThread的实例化会在SurfaceFlinger篇章阐述

1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp#createEventConnection
2sp<EventThreadConnection> EventThread::createEventConnection(
3        ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
4    //[2.2.4.10]
5    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
6                                     configChanged);
7}

2.2.4.10EventThreadConnection

构造一个EventThreadConnection

1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp#EventThreadConnection
2EventThreadConnection::EventThreadConnection(EventThread* eventThread,
3                                             ResyncCallback resyncCallback,
4                                             ISurfaceComposer::ConfigChanged configChanged)
5      : resyncCallback(std::move(resyncCallback)),
6        mConfigChanged(configChanged),
7        mEventThread(eventThread),
8        mChannel(gui::BitTube::DefaultSize) {}

2.2.4.11connection

同2.2.4.3类似,这里有一个显示的构造,实际上是传入的就是impl,这里的impl就是上面mScheduler管理的的EventThreadConnection的实例。

1//frameworks/native/libs/gui/IDisplayEventConnection.cpp#BpDisplayEventConnection#BpDisplayEventConnection
2class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
3public:
4    explicit BpDisplayEventConnection(const sp<IBinder>& impl)
5          : SafeBpInterface<IDisplayEventConnection>(impl, "BpDisplayEventConnection") {}
6};

2.2.4.12stealReceiveChannel

直接调用基类,是纯虚函数,找到对应的子类,BpDisplayEventConnection

1//frameworks/native/libs/gui/include/gui/IDisplayEventConnection.h
2class IDisplayEventConnection : public IInterface {
3    virtual status_t stealReceiveChannel(gui::BitTube* outChannel) = 0;
4};

BpDisplayEventConnection里面的函数会进行跨进程通信找到对应stealReceiveChannel函数

1//frameworks/native/libs/gui/IDisplayEventConnection.cpp#BpDisplayEventConnection#stealReceiveChannel
2class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
3    status_t stealReceiveChannel(gui::BitTube* outChannel) override {
4        return callRemote<decltype(
5            &IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
6                                                            outChannel);
7    }
8};

最终调用到EventThreadConnection,继承BnDisplayEventConnection

1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.h#EventThreadConnection
2class EventThreadConnection : public BnDisplayEventConnection {
3public:
4    EventThreadConnection(EventThread*, ResyncCallback,
5                          ISurfaceComposer::ConfigChanged configChanged);
6    virtual ~EventThreadConnection();
7    status_t stealReceiveChannel(gui::BitTube* outChannel) override;
8    ...
9};

stealReceiveChannel

1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp#stealReceiveChannel
2status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
3    outChannel->setReceiveFd(mChannel.moveReceiveFd());
4    return NO_ERROR;
5}

2.2.5initialize

承接上面的2.2.4之后,开始初始化,由于派生类NativeDisplayEventReceiver没有初始化函数,所以直接使用子类的初始化函数

 1//frameworks/native/libs/gui/DisplayEventDispatcher.cpp#initialize
 2status_t DisplayEventDispatcher::initialize() {
 3    //这个mReceiver是DisplayEventReceiver的实例,这里用于初始化的检验,是否已经完成初始化了
 4    status_t result = mReceiver.initCheck();
 5    if (result) {
 6        ALOGW("Failed to initialize display event receiver, status=%d", result);
 7        return result;
 8    }
 9
10    if (mLooper != nullptr) {
11        //这个方法比较关键,通过mReceiver的getFd获取到BitTube,用于操控底层的socket
12        //设置回调为this,这里的this就是DisplayEventDispatcher的实例
13        int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
14        if (rc < 0) {
15            return UNKNOWN_ERROR;
16        }
17    }
18
19    return OK;
20}

2.2.6 Choreographer中Vsync的注册图解

这块逻辑比较复杂,通过画图的方式在梳理上述流程会更加清晰明了

2.3Choreographer处理上一帧

处理一帧的逻辑是从回调开始,为了讲清楚来龙去脉,还得从native层的回调开始

实际上是本质是双向通信管道的socketpair的receive过程,并且获取到的回调信号事件进行分发处理

2.3.1回调处理

在上述Choreographer中Vsync的注册的2.2.5中,设置了DisplayEventDispatcher的实例的回调,那么这里就是开始的地方

 1//system/core/libutils/Looper.cpp#pollInner
 2int Looper::pollInner(int timeoutMillis) {
 3    ...
 4    for (size_t i = 0; i < mResponses.size(); i++) {
 5        Response& response = mResponses.editItemAt(i);
 6        if (response.request.ident == POLL_CALLBACK) {
 7            int fd = response.request.fd;
 8            int events = response.events;
 9            void* data = response.request.data;
10            ...
11            //[2.3.2]
12            int callbackResult = response.request.callback->handleEvent(fd, events, data);
13            ...
14            result = POLL_CALLBACK;
15        }
16    }
17    return result;
18}

2.3.2DisplayEventDispatcher.handleEvent

这里的callback实际上就是上面注册Vysnc信号传入的DisplayEventDispatcher实例的this

所以监听了mReceiveFd之后,当mSendFd写入数据时就能收到消息,并回调DisplayEventDispatcher的handleEvent函数

 1//frameworks/native/libs/gui/DisplayEventDispatcher.cpp#handleEvent
 2int DisplayEventDispatcher::handleEvent(int, int events, void*) {
 3    ...
 4    // Drain all pending events, keep the last vsync.
 5    nsecs_t vsyncTimestamp;
 6    PhysicalDisplayId vsyncDisplayId;
 7    uint32_t vsyncCount;
 8    //processPendingEvents,[2.3.3]
 9    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
10        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64
11              ", displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d",
12              this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount);
13        //一旦处理了延时事件之后,设置mWaitingForVsync=false,在
14        mWaitingForVsync = false;
15        //dispatchVsync用于处理Vysnc信号事件,[2.3.6]
16        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
17    }
18
19    return 1; // keep the callback
20}

2.3.3processPendingEvents

 1//frameworks/native/libs/gui/DisplayEventDispatcher.cpp#processPendingEvents
 2bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp,
 3                                                  PhysicalDisplayId* outDisplayId,
 4                                                  uint32_t* outCount) {
 5    bool gotVsync = false;
 6    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
 7    ssize_t n;
 8    //这个循环或重复获取getEvents,直到没有为止[2.3.4]
 9    while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
10        ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
11        for (ssize_t i = 0; i < n; i++) {
12            const DisplayEventReceiver::Event& ev = buf[i];
13            switch (ev.header.type) {
14                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
15                    //之后的 vsync 事件只会覆盖之前的信息
16                    gotVsync = true;
17                    *outTimestamp = ev.header.timestamp;
18                    *outDisplayId = ev.header.displayId;
19                    *outCount = ev.vsync.count;
20                    break;
21                ...
22            }
23        }
24    }
25    ...
26    return gotVsync;
27}

2.3.4getEvents

最终会调用到BitTube,使用socketpair的receive过程

 1//frameworks/native/libs/gui/DisplayEventReceiver.cpp#getEvents
 2ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
 3        size_t count) {
 4    return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count);
 5}
 6
 7ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel,
 8        Event* events, size_t count)
 9{
10    //[2.3.5]
11    return gui::BitTube::recvObjects(dataChannel, events, count);
12}

2.3.5recvObjects

最终是调用到BitTube,使用双向通信管道的socketpair的receive过程

关于socketpair

socket在内核中有一个发送缓冲区和一个接收缓冲区,send函数负责将数据存入socket的发送缓冲区,recv函数负责从socket的接收缓冲区中将数据拷贝到用户空间,recv和send不一定是一一对应,也就是说并不是send一次,就一定recv一次接收完,有可能send一次,recv多次才能接收完,也可能send多次,一次recv就接收完了

简单理解就是send发数据,recv就能够收到数据

1//frameworks/native/libs/gui/BitTube.cpp#recvObjects
2ssize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) {
3    char* vaddr = reinterpret_cast<char*>(events);
4    //vaddr为缓冲区的地址,count * objSize为缓冲区的大小
5    ssize_t size = tube->read(vaddr, count * objSize);
6    return size < 0 ? size : size / static_cast<ssize_t>(objSize);
7}

2.3.6DisplayEventDispatcher.dispatchVsync

这里的dispatchVsync实际上调用的是子类NativeDisplayEventReceiver中的dispatchVsync函数

 1//frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp#dispatchVsync
 2void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
 3                                               uint32_t count) {
 4    JNIEnv* env = AndroidRuntime::getJNIEnv();
 5
 6    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
 7    if (receiverObj.get()) {
 8        //这里jni开始回调到java层的DisplayEventReceiver#dispatchVsync,[2.3.7]
 9        env->CallVoidMethod(receiverObj.get(),
10                gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, displayId, count);
11        ALOGV("receiver %p ~ Returned from vsync handler.", this);
12    }
13
14    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
15}

2.3.7DisplayEventReceiver.dispatchVsync

从这里开始,事件的分发来到了java层

1//frameworks/base/core/java/android/view/DisplayEventReceiver.java#dispatchVsync
2private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
3    //[2.3.8]
4    onVsync(timestampNanos, physicalDisplayId, frame);
5}

2.3.8DisplayEventReceiver.onVsync

由于FrameDisplayEventReceiver继承了DisplayEventReceiver,所以实际上onVsync调用的是FrameDisplayEventReceiver中的方法

 1//frameworks/base/core/java/android/view/Choreographer.java#FrameDisplayEventReceiver#onVsync
 2private final class FrameDisplayEventReceiver extends DisplayEventReceiver
 3    implements Runnable {
 4    ...
 5    @Override
 6    public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
 7        long now = System.nanoTime();
 8        if (timestampNanos > now) {
 9            Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
10                  + " ms in the future!  Check that graphics HAL is generating vsync "
11                  + "timestamps using the correct timebase.");
12            timestampNanos = now;
13        }
14
15        //如果存在多个延时信号,那么当前时间只能处理一个同步信号Vsync
16        if (mHavePendingVsync) {
17            Log.w(TAG, "Already have a pending vsync event.  There should only be "
18                  + "one at a time.");
19        } else {
20            mHavePendingVsync = true;
21        }
22
23        mTimestampNanos = timestampNanos;
24        mFrame = frame;
25        //handler处理,使用的是Choreographer内部的mHandler,并且使用同步屏障,优先处理当前的事件
26        Message msg = Message.obtain(mHandler, this);
27        msg.setAsynchronous(true);
28        mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
29    }
30    
31    //在timestampNanos/TimeUtils.NANOS_PER_MS时间的时候开始处理doFrame
32    @Override
33    public void run() {
34        mHavePendingVsync = false;
35        //[2.3.9]
36        doFrame(mTimestampNanos, mFrame);
37    }
38}

2.3.9Choreographer.doFrame

这个接下来就是doFrame方法了,这个doFrame是Choreographer内部的,而不是FrameCallback中的doFrame

 1//frameworks/base/core/java/android/view/Choreographer.java#doFrame
 2void doFrame(long frameTimeNanos, int frame) {
 3    final long startNanos;
 4    synchronized (mLock) {
 5        if (!mFrameScheduled) {
 6            return; // no work to do
 7        }
 8        ...
 9        //计算掉帧逻辑,[2.3.9.2]   
10        long intendedFrameTimeNanos = frameTimeNanos;
11        startNanos = System.nanoTime();
12        final long jitterNanos = startNanos - frameTimeNanos;
13        if (jitterNanos >= mFrameIntervalNanos) {
14            final long skippedFrames = jitterNanos / mFrameIntervalNanos;
15            if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
16                Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
17                      + "The application may be doing too much work on its main thread.");
18            }
19            final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
20            frameTimeNanos = startNanos - lastFrameOffset;
21        }
22
23        if (frameTimeNanos < mLastFrameTimeNanos) {
24            scheduleVsyncLocked();
25            return;
26        }
27
28        if (mFPSDivisor > 1) {
29            long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
30            if (timeSinceVsync < (mFrameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
31                scheduleVsyncLocked();
32                return;
33            }
34        }
35        //[2.3.9.3]
36        mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
37        //[2.3.9.1]
38        mFrameScheduled = false;
39        mLastFrameTimeNanos = frameTimeNanos;
40    }
41
42    //这里面的Trace.traceBegin和traceEnd,通过androidsdk的systrace可以捕获这段信息,然后再将对应的html展示出来
43    try {
44        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
45        AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
46        //[2.3.9.3]
47        mFrameInfo.markInputHandlingStart();
48        //[2.3.9.4]
49        doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
50        //[2.3.9.3]
51        mFrameInfo.markAnimationsStart();
52        //[2.3.9.4]
53        doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
54        doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);
55        //[2.3.9.3]
56        mFrameInfo.markPerformTraversalsStart();
57        //[2.3.9.4]
58        doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
59        doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
60    } finally {
61        AnimationUtils.unlockAnimationClock();
62        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
63    }
64    ...
65}

下面的doFrame方法还是比较复杂的,拆解开来主要关注几点

2.3.9.1变量mFrameScheduled

mFrameScheduled必须是true才能进入处理分发事件,而且同一时间只能处理一个分发事件,分发完成时间也不会马上复位。

这个会跟后面的下一帧的Vsync请求联系,直到2.4.9的scheduleFrameLocked请求事件之后,才会让上面的分发再一次得到处理,mFrameScheduled就是Choreographer.java里面的精髓所在,是控制完成16.7ms的关键。

2.3.9.2计算掉帧逻辑

 1//frameworks/base/core/java/android/view/Choreographer.java#doFrame
 2final long startNanos;
 3    synchronized (mLock) {
 4        ...
 5        long intendedFrameTimeNanos = frameTimeNanos;
 6        startNanos = System.nanoTime();
 7        final long jitterNanos = startNanos - frameTimeNanos;
 8        if (jitterNanos >= mFrameIntervalNanos) {
 9            final long skippedFrames = jitterNanos / mFrameIntervalNanos;
10            if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
11                Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
12                        + "The application may be doing too much work on its main thread.");
13            }
14        }
15        ...
16    }
17}

2.3.9.3记录帧绘制信息

1//frameworks/base/core/java/android/view/Choreographer.java#doFrame
2FrameInfo mFrameInfo = new FrameInfo();
3
4mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
5mFrameInfo.markInputHandlingStart();
6mFrameInfo.markAnimationsStart();
7mFrameInfo.markPerformTraversalsStart();

其中mFrameInfo,内部维护了一个长度为9的long类型的数组,每个数组元素都有具体含义,作用是记录doCallbacks方法时间

 1//frameworks/base/graphics/java/android/graphics/FrameInfo.java
 2public final class FrameInfo {
 3
 4    public long[] frameInfo = new long[9];
 5    // Various flags set to provide extra metadata about the current frame
 6    private static final int FLAGS = 0;
 7    // Is this the first-draw following a window layout?
 8    public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
 9    // A renderer associated with just a Surface, not with a ViewRootImpl instance.
10    public static final long FLAG_SURFACE_CANVAS = 1 << 2;
11
12    @LongDef(flag = true, value = {
13            FLAG_WINDOW_LAYOUT_CHANGED, FLAG_SURFACE_CANVAS })
14    @Retention(RetentionPolicy.SOURCE)
15    public @interface FrameInfoFlags {}
16    // The intended vsync time, unadjusted by jitter
17    private static final int INTENDED_VSYNC = 1;
18    // Jitter-adjusted vsync time, this is what was used as input into the
19    // animation & drawing system
20    private static final int VSYNC = 2;
21    // The time of the oldest input event
22    private static final int OLDEST_INPUT_EVENT = 3;
23    // The time of the newest input event
24    private static final int NEWEST_INPUT_EVENT = 4;
25    // When input event handling started
26    private static final int HANDLE_INPUT_START = 5;
27    // When animation evaluations started
28    private static final int ANIMATION_START = 6;
29    // When ViewRootImpl#performTraversals() started
30    private static final int PERFORM_TRAVERSALS_START = 7;
31    // When View:draw() started
32    private static final int DRAW_START = 8;
33
34    public void setVsync(long intendedVsync, long usedVsync) {
35        frameInfo[INTENDED_VSYNC] = intendedVsync;
36        frameInfo[VSYNC] = usedVsync;
37        frameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
38        frameInfo[NEWEST_INPUT_EVENT] = 0;
39        frameInfo[FLAGS] = 0;
40    }
41
42    public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
43        if (inputEventOldestTime < frameInfo[OLDEST_INPUT_EVENT]) {
44            frameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
45        }
46        if (inputEventTime > frameInfo[NEWEST_INPUT_EVENT]) {
47            frameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
48        }
49    }
50
51    public void markInputHandlingStart() {
52        frameInfo[HANDLE_INPUT_START] = System.nanoTime();
53    }
54
55    public void markAnimationsStart() {
56        frameInfo[ANIMATION_START] = System.nanoTime();
57    }
58
59    public void markPerformTraversalsStart() {
60        frameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
61    }
62
63    public void markDrawStart() {
64        frameInfo[DRAW_START] = System.nanoTime();
65    }
66
67    public void addFlags(@FrameInfoFlags long flags) {
68        frameInfo[FLAGS] |= flags;
69    }
70}

2.3.9.4doCallbacks

执行doCallbacks方法,获取mCallbackQueues中的对应mHead队列中的元素

1//frameworks/base/core/java/android/view/Choreographer.java#doFrame
2doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
3doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
4doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);
5doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
6doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);

这里就调用到了doCallbacks方法

 1//frameworks/base/core/java/android/view/Choreographer.java#doCallbacks
 2void doCallbacks(int callbackType, long frameTimeNanos) {
 3    CallbackRecord callbacks;
 4    synchronized (mLock) {
 5        final long now = System.nanoTime();
 6        //这里开始获取mCallbackQueues中的对应mHead队列中的元素组
 7        callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
 8            now / TimeUtils.NANOS_PER_MS);
 9        if (callbacks == null) {
10            return;
11        }
12        //获取到CallbackRecord类型的队列后,设置状态为true
13        mCallbacksRunning = true;
14        if (callbackType == Choreographer.CALLBACK_COMMIT) {
15            final long jitterNanos = now - frameTimeNanos;
16            Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
17            if (jitterNanos >= 2 * mFrameIntervalNanos) {
18                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
19                    + mFrameIntervalNanos;
20                frameTimeNanos = now - lastFrameOffset;
21                mLastFrameTimeNanos = frameTimeNanos;
22            }
23        }
24    }
25    //主要耗时在这里,包括trace记录也是从这里开始
26    try {
27        Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
28        for (CallbackRecord c = callbacks; c != null; c = c.next) {
29            //[2.3.9.5]
30            c.run(frameTimeNanos);
31        }
32    } finally {
33        synchronized (mLock) {
34            //CallbackRecord类型的队列Running完成之后,设置状态为false
35            mCallbacksRunning = false;
36            do {
37                final CallbackRecord next = callbacks.next;
38                recycleCallbackLocked(callbacks);
39                callbacks = next;
40            } while (callbacks != null);
41        }
42        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
43    }
44}

这里面有一个recycleCallbackLocked方法,是为了让其置为空

1//frameworks/base/core/java/android/view/Choreographer.java#recycleCallbackLocked
2private void recycleCallbackLocked(CallbackRecord callback) {
3    callback.action = null;
4    callback.token = null;
5    callback.next = mCallbackPool;
6    mCallbackPool = callback;
7}

2.3.9.5CallbackRecord.run

最重要的就是run方法,回调到CallbackRecord的run方法,具体关于run方法的图解,可以直接跳转到2.4.25关于Choreographer的流程

 1//frameworks/base/core/java/android/view/Choreographer.java#CallbackRecord#run
 2private static final class CallbackRecord {
 3    public CallbackRecord next;
 4    public long dueTime;
 5    public Object action; // Runnable or FrameCallback
 6    public Object token;
 7
 8    @UnsupportedAppUsage
 9    public void run(long frameTimeNanos) {
10        //这里根据token判断传入的api方式
11        //其中postFrameCallback调用的api定义token为FRAME_CALLBACK_TOKEN,执行doFrame
12        //其中postCallback调用的api定义token为其他,run
13        if (token == FRAME_CALLBACK_TOKEN) {
14            ((FrameCallback)action).doFrame(frameTimeNanos);
15        } else {
16            ((Runnable)action).run();
17        }
18    }
19}

2.3.10Choreographer处理上一帧图解

2.4下一帧的Vsync请求

这里的Vsync信号是由SurfaceFlinger中创建HWC触发的,具体关于Vysnc会在单独的章节阐述这个流程

下一帧的Vsync的请求的处理,实际上是本质是双向通信管道的socketpair的send过程

VSync信号

VSync并不是一个实际的信号,可以认为是一条通知,EventThread收到通知之后自己构造一个Event,然后发送出去VSync类型事件构造好了之后通过条件变量唤醒陷入wait状态的EventThread内部线程,它会从mPendingEvents中拿到最头部事件调用dispatchEvent将事件分发给感兴趣的监听者,感兴趣的监听者即是向EventThread请求了Vsync的EventThreadConnection。dispatchEvent的实现很简单,最终就是通过gui::BitTube的sendObjects函数向mSendFd中写入数据,另一端监听了mReceiveFd的进程就能够收到消息,知道Vsync到来了,然后完成绘制工作

我们下面以Animation为例,使用的是postFrameCallback,定义token为FRAME_CALLBACK_TOKEN

2.4.1ObjectAnimator.start

1//frameworks/base/core/java/android/animation/ObjectAnimator.java#start
2@Override
3public void start() {
4    AnimationHandler.getInstance().autoCancelBasedOn(this);
5    //[2.4.2]
6    super.start();
7}

2.4.2ValueAnimator.start

 1//frameworks/base/core/java/android/animation/ValueAnimator.java#start
 2@Override
 3public void start() {
 4    start(false);
 5}
 6
 7private void start(boolean playBackwards) {
 8    if (Looper.myLooper() == null) {
 9        throw new AndroidRuntimeException("Animators may only be run on Looper threads");
10    }
11    ...
12    //[2.4.3]
13    addAnimationCallback(0);
14    ...
15}

2.4.3ValueAnimator.addAnimationCallback

1//frameworks/base/core/java/android/animation/ValueAnimator.java#addAnimationCallback
2private void addAnimationCallback(long delay) {
3    if (!mSelfPulse) {
4        return;
5    }
6    //[2.4.4]
7    getAnimationHandler().addAnimationFrameCallback(this, delay);
8}

2.4.4AnimationHandler.addAnimationFrameCallback

 1//frameworks/base/core/java/android/animation/AnimationHandler.java#addAnimationFrameCallback
 2public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
 3    if (mAnimationCallbacks.size() == 0) {
 4        //继续下一帧的获取[2.4.5]
 5        getProvider().postFrameCallback(mFrameCallback);
 6    }
 7    ...
 8}
 9
10//最终回调
11private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
12    @Override
13    //Choreographer回调,处理当前动画的
14    public void doFrame(long frameTimeNanos) {
15        //处理当前动画的
16        doAnimationFrame(getProvider().getFrameTime());
17        if (mAnimationCallbacks.size() > 0) {
18            //继续下一帧的获取[2.4.5]
19            getProvider().postFrameCallback(this);
20        }
21    }
22};

2.4.5getProvider().postFrameCallback

这里的provider实际上AnimationHandler内部维护了一个AnimationFrameCallbackProvider用于申请下一个Vsync信号

 1//frameworks/base/core/java/android/animation/AnimationHandler.java#postFrameCallback
 2//内部维护了一个Choreographer单例,直接调用
 3private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
 4
 5    final Choreographer mChoreographer = Choreographer.getInstance();
 6
 7    @Override
 8    public void postFrameCallback(Choreographer.FrameCallback callback) {
 9        //[2.4.6]
10        mChoreographer.postFrameCallback(callback);
11    }
12    ...
13}

2.4.6postFrameCallback

 1//frameworks/base/core/java/android/view/Choreographer.java#postFrameCallback
 2public void postFrameCallback(FrameCallback callback) {
 3    postFrameCallbackDelayed(callback, 0);
 4}
 5
 6public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
 7    if (callback == null) {
 8        throw new IllegalArgumentException("callback must not be null");
 9    }
10
11    postCallbackDelayedInternal(CALLBACK_ANIMATION,
12                                callback, FRAME_CALLBACK_TOKEN, delayMillis);
13}
14
15// callbackType为动画,action为mAnimationFrameCallback
16// token为FRAME_CALLBACK_TOKEN,delayMillis=0
17private void postCallbackDelayedInternal(int callbackType,
18                                         Object action, Object token, long delayMillis) {
19    //默认DEBUG_FRAMES是false,如果需要打印手动设置DEBUG_FRAMES为true
20    if (DEBUG_FRAMES) {
21        Log.d(TAG, "PostCallback: type=" + callbackType
22              + ", action=" + action + ", token=" + token
23              + ", delayMillis=" + delayMillis);
24    }
25
26    synchronized (mLock) {
27        final long now = SystemClock.uptimeMillis();
28        final long dueTime = now + delayMillis;
29        //添加到mCallbackQueues队列
30        mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
31        //如果传进里面的时间比现在的时间少,那么就立即进行
32        if (dueTime <= now) {
33            //[2.4.9]
34            scheduleFrameLocked(now);
35        //如果传进里面的时间比现在的时间多,那么就handler延时处理事件
36        } else {
37            //[2.4.7]
38            Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
39            msg.arg1 = callbackType;
40            msg.setAsynchronous(true);
41            mHandler.sendMessageAtTime(msg, dueTime);
42        }
43    }
44}

2.4.7mHandler消息处理事件MSG_DO_SCHEDULE_CALLBACK

mHandler处理消息,消息内容为MSG_DO_SCHEDULE_CALLBACK

 1//frameworks/base/core/java/android/view/Choreographer.java#FrameHandler#MSG_DO_SCHEDULE_CALLBACK
 2private final class FrameHandler extends Handler {
 3    @Override
 4    public void handleMessage(Message msg) {
 5        switch (msg.what) {
 6            ...
 7            case MSG_DO_SCHEDULE_CALLBACK:
 8                //[2.4.8]
 9                doScheduleCallback(msg.arg1);
10                break;
11        }
12    }
13}

2.4.8doScheduleCallback

 1//frameworks/base/core/java/android/view/Choreographer.java#MSG_DO_SCHEDULE_CALLBACK
 2void doScheduleCallback(int callbackType) {
 3    synchronized (mLock) {
 4        if (!mFrameScheduled) {
 5            final long now = SystemClock.uptimeMillis();
 6            if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
 7                //[2.4.9]
 8                scheduleFrameLocked(now);
 9            }
10        }
11    }
12}

2.4.9scheduleFrameLocked

 1//frameworks/base/core/java/android/view/Choreographer.java#scheduleFrameLocked
 2private void scheduleFrameLocked(long now) {
 3    if (!mFrameScheduled) {
 4        mFrameScheduled = true;
 5        //默认USE_VSYNC为true,使用的是垂直同步
 6        if (USE_VSYNC) {
 7            if (isRunningOnLooperThreadLocked()) {
 8                //[2.4.12]
 9                scheduleVsyncLocked();
10            } else {
11                //[2.4.10]
12                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
13                msg.setAsynchronous(true);
14                mHandler.sendMessageAtFrontOfQueue(msg);
15            }
16        } else {
17            final long nextFrameTime = Math.max(
18                mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
19            if (DEBUG_FRAMES) {
20                Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
21            }
22            Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
23            msg.setAsynchronous(true);
24            mHandler.sendMessageAtTime(msg, nextFrameTime);
25        }
26    }
27}

2.4.10mHandler消息处理事件MSG_DO_SCHEDULE_VSYNC

 1//frameworks/base/core/java/android/view/Choreographer.java#FrameHandler#MSG_DO_SCHEDULE_VSYNC
 2private final class FrameHandler extends Handler {
 3    @Override
 4    public void handleMessage(Message msg) {
 5        switch (msg.what) {
 6            ...
 7            case MSG_DO_SCHEDULE_VSYNC:
 8                //[2.4.11]
 9                doScheduleVsync();
10                break;
11        }
12    }
13}

2.4.11doScheduleVsync

1//frameworks/base/core/java/android/view/Choreographer.java#doScheduleVsync
2void doScheduleVsync() {
3    synchronized (mLock) {
4        if (mFrameScheduled) {
5            //[2.4.12]
6            scheduleVsyncLocked();
7        }
8    }
9}

2.4.12scheduleVsyncLocked

1//frameworks/base/core/java/android/view/Choreographer.java#scheduleVsyncLocked
2private void scheduleVsyncLocked() {
3    //[2.4.13]
4    mDisplayEventReceiver.scheduleVsync();
5}

2.4.13scheduleVsync

这里开始从java层调用到native层往下

 1//frameworks/base/core/java/android/view/DisplayEventReceiver.java#scheduleVsync
 2public void scheduleVsync() {
 3    if (mReceiverPtr == 0) {
 4        Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
 5              + "receiver has already been disposed.");
 6    } else {
 7        //[2.4.14]
 8        nativeScheduleVsync(mReceiverPtr);
 9    }
10}

2.4.14nativeScheduleVsync

1//frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp#nativeScheduleVsync
2static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
3    sp<NativeDisplayEventReceiver> receiver =
4            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
5    //[2.4.15]
6    status_t status = receiver->scheduleVsync();
7    ...
8}

2.4.15scheduleVsync

由于NativeDisplayEventReceiver是继承基类DisplayEventDispatcher,所以这里调用到了基类的函数

 1//frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp#NativeDisplayEventReceiver
 2class NativeDisplayEventReceiver : public DisplayEventDispatcher {
 3public:
 4    NativeDisplayEventReceiver(JNIEnv* env,
 5            jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource,
 6            jint configChanged);
 7
 8    void dispose();
 9
10protected:
11    virtual ~NativeDisplayEventReceiver();
12
13private:
14    jobject mReceiverWeakGlobal;
15    sp<MessageQueue> mMessageQueue;
16
17    void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override;
18    void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
19    void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
20                               int32_t configId, nsecs_t vsyncPeriod) override;
21};

scheduleVsync

 1//frameworks/native/libs/gui/DisplayEventDispatcher.cpp#scheduleVsync
 2status_t DisplayEventDispatcher::scheduleVsync() {
 3    //这个的mWaitingForVsync表示同一时间只能处理一次Vysnc信号
 4    if (!mWaitingForVsync) {
 5        ALOGV("dispatcher %p ~ Scheduling vsync.", this);
 6        nsecs_t vsyncTimestamp;
 7        PhysicalDisplayId vsyncDisplayId;
 8        uint32_t vsyncCount;
 9        //这个processPendingEvents函数会在后面解释,是双向通信管道的socketpair的receive过程,用于获取vysnc信号
10        //这里的作用实际上是规定时间内,发送太多次vynsc,没来的及处理的error日志信息
11        //processPendingEvents,处理Vysnc信号事件的[2.3.2],主要是处理延时信号
12        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
13            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
14                  ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
15        }
16        //[2.4.16]
17        status_t status = mReceiver.requestNextVsync();
18
19        mWaitingForVsync = true;
20    }
21    return OK;
22}

2.4.16DisplayEventReceiver.requestNextVsync

该方法的作用请求下一次Vsync信息处理

1//frameworks/native/libs/gui/DisplayEventReceiver.cpp#requestNextVsync
2status_t DisplayEventReceiver::requestNextVsync() {
3    if (mEventConnection != nullptr) {
4        //[2.4.17]
5        mEventConnection->requestNextVsync();
6        return NO_ERROR;
7    }
8    return NO_INIT;
9}

2.4.17BpDisplayEventConnection.requestNextVsync

由于对应的IDisplayEventConnection的定义是requestNextVsync是纯虚函数,所以最终调用是在BpDisplayEventConnection中。显然这里面有一个binder过程,这里面的SafeBpInterface是IInterface这个基类的封装类,对其做了一次封装用于这里的场景

1//frameworks/native/libs/gui/IDisplayEventConnection.cpp#requestNextVsync
2class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
3    void requestNextVsync() override {
4        //[2.4.18]
5        callRemoteAsync<decltype(&IDisplayEventConnection::requestNextVsync)>(
6            Tag::REQUEST_NEXT_VSYNC);
7    }
8};

IDisplayEventConnection初始化,其中传入的impl就是对应的服务端

1//frameworks/native/libs/gui/IDisplayEventConnection.cpp#BpDisplayEventConnection
2class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
3public:
4    explicit BpDisplayEventConnection(const sp<IBinder>& impl)
5          : SafeBpInterface<IDisplayEventConnection>(impl, "BpDisplayEventConnection") {}
6    ...
7}

2.4.18EventThreadConnection.requestNextVsync

事实上传入的impl就是EventThreadConnection的实例

 1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.h
 2class EventThreadConnection : public BnDisplayEventConnection {
 3public:
 4    EventThreadConnection(EventThread*, ResyncCallback,
 5                          ISurfaceComposer::ConfigChanged configChanged);
 6    virtual ~EventThreadConnection();
 7
 8    virtual status_t postEvent(const DisplayEventReceiver::Event& event);
 9
10    status_t stealReceiveChannel(gui::BitTube* outChannel) override;
11    status_t setVsyncRate(uint32_t rate) override;
12    void requestNextVsync() override; // asynchronous
13    void requestLatestConfig() override; // asynchronous
14
15    const ResyncCallback resyncCallback;
16    VSyncRequest vsyncRequest = VSyncRequest::None;
17    ISurfaceComposer::ConfigChanged mConfigChanged =
18            ISurfaceComposer::ConfigChanged::eConfigChangedSuppress;
19    bool mForcedConfigChangeDispatch = false;
20
21private:
22    virtual void onFirstRef();
23    EventThread* const mEventThread;
24    gui::BitTube mChannel;
25};

通过binder,最终调用到服务端实现。可以看到requestNextVsync的最后实际上就是用于一个信号的唤醒,notify_all

 1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp#requestNextVsync
 2void EventThreadConnection::requestNextVsync() {
 3    ATRACE_NAME("requestNextVsync");
 4    mEventThread->requestNextVsync(this);
 5}
 6
 7void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
 8    if (connection->resyncCallback) {
 9        connection->resyncCallback();
10    }
11
12    std::lock_guard<std::mutex> lock(mMutex);
13
14    if (connection->vsyncRequest == VSyncRequest::None) {
15        connection->vsyncRequest = VSyncRequest::Single;
16        //[2.4.19]
17        mCondition.notify_all();
18    }
19}

2.4.19EventThread::threadMain#wait_for

notify_all这里是用于唤醒,有唤醒那么等待。这里有threadMain的函数,是由SurfaceFlinger初始化的时候启动的线程函数。这个函数主要是用于收集和处理唤醒事件

  1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp#EventThread#requestNextVsync
  2void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
  3    DisplayEventConsumers consumers;
  4
  5    while (mState != State::Quit) {
  6        std::optional<DisplayEventReceiver::Event> event;
  7
  8        // Determine next event to dispatch.
  9        if (!mPendingEvents.empty()) {
 10            //std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
 11            //GUARDED_BY 是线程的安全注解
 12            //Event队列不为空,取出队列中的元素,这里指的是之前唤醒的Vysnc事件
 13            event = mPendingEvents.front();
 14            mPendingEvents.pop_front();
 15			
 16            switch (event->header.type) {
 17                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
 18                    if (event->hotplug.connected && !mVSyncState) {
 19                        mVSyncState.emplace(event->header.displayId);
 20                    } else if (!event->hotplug.connected && mVSyncState &&
 21                               mVSyncState->displayId == event->header.displayId) {
 22                        mVSyncState.reset();
 23                    }
 24                    break;
 25				//回调mInterceptVSyncsCallback处理
 26                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
 27                    if (mInterceptVSyncsCallback) {
 28                        mInterceptVSyncsCallback(event->header.timestamp);
 29                    }
 30                    break;
 31                case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
 32                    mLastConfigChangeEvent = *event;
 33                    break;
 34            }
 35        }
 36
 37        bool vsyncRequested = false;
 38
 39        auto it = mDisplayEventConnections.begin();
 40        while (it != mDisplayEventConnections.end()) {
 41            if (const auto connection = it->promote()) {
 42                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
 43
 44                if (event && shouldConsumeEvent(*event, connection)) {
 45                    if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
 46                        connection->mForcedConfigChangeDispatch) {
 47                        connection->mForcedConfigChangeDispatch = false;
 48                    }
 49                    consumers.push_back(connection);
 50                }
 51
 52                ++it;
 53            } else {
 54                it = mDisplayEventConnections.erase(it);
 55            }
 56        }
 57
 58        //处理分发的事件
 59        if (!consumers.empty()) {
 60            //[2.4.20]
 61            dispatchEvent(*event, consumers);
 62            consumers.clear();
 63        }
 64        //开始下一帧的申请
 65        State nextState;
 66        if (mVSyncState && vsyncRequested) {
 67            nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
 68        } else {
 69            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
 70            nextState = State::Idle;
 71        }
 72
 73        if (mState != nextState) {
 74            if (mState == State::VSync) {
 75                mVSyncSource->setVSyncEnabled(false);
 76            } else if (nextState == State::VSync) {
 77                mVSyncSource->setVSyncEnabled(true);
 78            }
 79
 80            mState = nextState;
 81        }
 82
 83        if (event) {
 84            continue;
 85        }
 86
 87        //继续等待,直到开始有唤醒
 88        if (mState == State::Idle) {
 89            mCondition.wait(lock);
 90        } else {
 91            const std::chrono::nanoseconds timeout =
 92                    mState == State::SyntheticVSync ? 16ms : 1000ms;
 93            //上面传递过来的notify_all用于这里的唤醒
 94            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
 95                if (mState == State::VSync) {
 96                    ...
 97                    auto pos = debugInfo.find('\n');
 98                    while (pos != std::string::npos) {
 99                        ALOGW("%s", debugInfo.substr(0, pos).c_str());
100                        debugInfo = debugInfo.substr(pos + 1);
101                        pos = debugInfo.find('\n');
102                    }
103                }
104
105                const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
106                const auto expectedVSyncTime = now + timeout.count();
107                //唤醒之后,首先把唤醒的这个信号的信息,存储在Event队列中
108                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
109                                                   ++mVSyncState->count, expectedVSyncTime));
110            }
111        }
112    }
113}

2.4.20dispatchEvent

 1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp#EventThread#dispatchEvent
 2void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
 3                                const DisplayEventConsumers& consumers) {
 4    for (const auto& consumer : consumers) {
 5        //开始处理这里的事件[2.4.21]
 6        switch (consumer->postEvent(event)) {
 7            case NO_ERROR:
 8                break;
 9
10            case -EAGAIN:
11                // TODO: Try again if pipe is full.
12                ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
13                      toString(*consumer).c_str());
14                break;
15
16            default:
17                // Treat EPIPE and other errors as fatal.
18                removeDisplayEventConnectionLocked(consumer);
19        }
20    }
21}

2.4.21postEvent

1//frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp#EventThreadConnection#postEvent
2status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
3    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
4    return size < 0 ? status_t(size) : status_t(NO_ERROR);
5}

postEvent,可以发现实际上最终调用到的就是sendObjects

1//frameworks/native/libs/gui/DisplayEventReceiver.cpp#sendEvents
2ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
3        Event const* events, size_t count)
4{
5    //[2.4.22]
6    return gui::BitTube::sendObjects(dataChannel, events, count);
7}

2.4.22sendObjects

这里的BitTube实际上就是封装的socketpair

1//frameworks/native/libs/gui/include/private/gui/BitTube.h#sendObjects
2template <typename T>
3static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) {
4    //[2.4.23]
5    return sendObjects(tube, events, count, sizeof(T));
6}

2.4.23sendObjects

走到这里,实际上就已经不难了,原理就是socket通信

1//frameworks/native/libs/gui/BitTube.cpp#sendObjects
2ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
3    const char* vaddr = reinterpret_cast<const char*>(events);
4    ssize_t size = tube->write(vaddr, count * objSize);
5    return size < 0 ? size : size / static_cast<ssize_t>(objSize);
6}

2.4.34下一帧的Vsync请求流程图如下所示

java流程

c++流程

总的流程

2.4.25关于Choreographer的流程

结合2.3的Choreographer处理上一帧流程和2.4的下一帧的Vsync请求流程,具体可以看到下图

承接2.3.9.5所示的run方法,不同的action(action为Runnable或者 FrameCallback两者的子类)和callbackType(CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_INSETS_ANIMATION、CALLBACK_TRAVERSAL和CALLBACK_COMMIT),最终回调用不同的方法。

2.4.25.1FrameCallback.doFrame

Choreographer的FrameCallback用的callbackType只能为CALLBACK_ANIMATION,这里会会调到FrameCallback子类的doFrame方法

1//frameworks/base/core/java/android/view/Choreographer.javapostFrameCallbackDelayed
2public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
3    if (callback == null) {
4        throw new IllegalArgumentException("callback must not be null");
5    }
6
7    postCallbackDelayedInternal(CALLBACK_ANIMATION,
8                                callback, FRAME_CALLBACK_TOKEN, delayMillis);
9}

表2.1postFrameCallbackDelayed子类

子类名 回调名
AnimationHandler.java mFrameCallback
ViewRootImpl.java mRenderProfiler
TextView.java mTickCallback
mStartCallback
SfVsyncFrameCallbackProvider.java callback
BackdropFrameRenderer.java BackdropFrameRenderer::this
TiledImageView.java mFrameCallback
SurfaceAnimationRunner.java SurfaceAnimationRunner::startAnimations
WindowAnimator.java mAnimationFrameCallback
WindowTracing.java mFrameCallback
BubbleStackView.java new Choreographer.FrameCallback()
FrameProtoTracer.java FrameProtoTracer::this

举例说明

2.5.25.2Runnable.run

这里的5种类型的run,比如这就是进入了事件分发的机制。事实上,callbackType为CALLBACK_ANIMATION更多一点,这里会会调到Runnable子类的run方法

1)callbackType为CALLBACK_INPUT

 1//frameworks/base/core/java/android/view/ViewRootImpl.java#doConsumeBatchedInput
 2final class ConsumeBatchedInputRunnable implements Runnable {
 3    @Override
 4    public void run() {
 5        mConsumeBatchedInputScheduled = false;
 6        if (doConsumeBatchedInput(mChoreographer.getFrameTimeNanos())) {
 7            //我们想要继续并安排在下一帧消费延时输入事件。
 8            //如果不先消费这一批次的输入事件,我们会等到有更多的输入事件挂起,并且可能会因过程中发生的其他事情而饿死
 9            scheduleConsumeBatchedInput();
10        }
11    }
12}
13
14boolean doConsumeBatchedInput(long frameTimeNanos) {
15    final boolean consumedBatches;
16    if (mInputEventReceiver != null) {
17        consumedBatches = mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos);
18    } else {
19        consumedBatches = false;
20    }
21    doProcessInputEvents();
22    return consumedBatches;
23}
24
25void scheduleConsumeBatchedInput() {
26    if (!mConsumeBatchedInputScheduled && !mConsumeBatchedInputImmediatelyScheduled) {
27        mConsumeBatchedInputScheduled = true;
28        mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
29                                    mConsumedBatchedInputRunnable, null);
30    }
31}

input最终会调用到DecorView 的 dispatchTouchEvent,这就到了我们熟悉的 Input 事件分发,这里不展开描述事件分发机制。

2)callbackType为CALLBACK_ANIMATION

 1//frameworks/base/core/java/android/view/View.java
 2//由于postOnAnimation的参数是Runnable的动作,子类或者是匿名内部类来进行回调就可以收到回调的Vysnc信号事件
 3public void postOnAnimation(Runnable action) {
 4    final AttachInfo attachInfo = mAttachInfo;
 5    if (attachInfo != null) {
 6        //调用postCallback的api,使用的是runnable形式
 7        attachInfo.mViewRootImpl.mChoreographer.postCallback(
 8            Choreographer.CALLBACK_ANIMATION, action, null);
 9    } else {
10        // Postpone the runnable until we know
11        // on which thread it needs to run.
12        getRunQueue().post(action);
13    }
14}

由于上面的action,是由其他类去注入的,因此会回调用到 View.postOnAnimation的操作,如下表所示

举例如下,RecyclerView.java

3)callbackType为CALLBACK_TRAVERSAL

 1//frameworks/base/core/java/android/view/ViewRootImpl.java#scheduleTraversals
 2//这个scheduleTraversals方法设置Runnable的回调
 3void scheduleTraversals() {
 4    if (!mTraversalScheduled) {
 5        mTraversalScheduled = true;
 6        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
 7        mChoreographer.postCallback(
 8            Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
 9        notifyRendererOfFramePending();
10        pokeDrawLockIfNeeded();
11    }
12}
13
14//Vsync信号分发事件回调到这里的run方法
15final class TraversalRunnable implements Runnable {
16    @Override
17    public void run() {
18        doTraversal();
19    }
20}
21//这里做真正的measure、layout和draw操作,这里就是具体的绘制三部曲流程了
22void doTraversal() {
23    if (mTraversalScheduled) {
24        mTraversalScheduled = false;
25        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
26
27        if (mProfile) {
28            Debug.startMethodTracing("ViewAncestor");
29        }
30        //这里做真正的measure、layout和draw操作,这里就是具体的绘制三部曲流程了
31        performTraversals();
32
33        if (mProfile) {
34            Debug.stopMethodTracing();
35            mProfile = false;
36        }
37    }
38}

举例说明

3.5 Choreographer应用

许多性能监控的手段都是利用 Choreographer 来做的,除了自带的掉帧计算,Choreographer 提供的 FrameCallback 和 FrameInfo 都给 App 暴露了接口,让 App 开发者可以通过这些方法监控自身 App 的性能,其中常用的方法如下:

  1. 利用 FrameCallback 的 doFrame 回调
  2. 利用 FrameInfo 进行监控
    1. 使用 :adb shell dumpsys gfxinfo framestats
    2. 示例 :adb shell dumpsys gfxinfo framestats
  3. 利用 SurfaceFlinger 进行监控
    1. 使用 :adb shell dumpsys SurfaceFlinger –latency
    2. 示例 :adb shell dumpsys SurfaceFlinger –latency /

3.5.1FrameCallback 接口

利用 FrameCallback 的 doFrame 回调用于监控应用的帧率,类似开源项目TinyDancer 就是使用了这个方法来计算 FPS (https://github.com/friendlyrobotnyc/TinyDancer)

1//frameworks/base/core/java/android/view/Choreographer.java#FrameCallback
2public interface FrameCallback {
3    public void doFrame(long frameTimeNanos);
4}

开始自定义处理帧逻辑

 1Choreographer.getInstance().postFrameCallback(new Choreographer.postFrameCallback(){
 2    @override
 3    public void doFrame(long now)
 4    {
 5        //计算上一次now和这一次now的时间间隔
 6        mGap = now - mNext;
 7        mNext = now;
 8    }
 9});
10
11public void postFrameCallback(FrameCallback callback, long delayMillis) {
12    ......
13    postCallbackDelayedInternal(CALLBACK_ANIMATION,
14            callback, FRAME_CALLBACK_TOKEN, delayMillis);
15}

3.5.2FrameInfo 进行监控

截取部分数据

 1picasso:/ $ dumpsys gfxinfo com.miui.home framestats
 2Applications Graphics Acceleration Info:
 3Uptime: 18524925 Realtime: 30993029
 4
 5** Graphics info for pid 24987 [com.miui.home] **
 6
 7Stats since: 15566429111717ns
 8Total frames rendered: 976
 9Janky frames: 179 (18.34%)
1050th percentile: 5ms
1190th percentile: 11ms
1295th percentile: 19ms
1399th percentile: 150ms
14Number Missed Vsync: 31
15Number High input latency: 710
16Number Slow UI thread: 49
17Number Slow bitmap uploads: 19
18Number Slow issue draw commands: 45
19Number Frame deadline missed: 77
20HISTOGRAM: 5ms=667 6ms=65 7ms=49 8ms=35 9ms=30 10ms=30 11ms=13 12ms=8 13ms=10 14ms=2 15ms=6 16ms=4 17ms=2 18ms=4 19ms=3 20ms=1 21ms=2 22ms=1 23ms=4 24ms=1 25ms=2 26ms=0 27ms=0 28ms=1 29ms=1 30ms=0 31ms=0 32ms=2 34ms=0 36ms=0 38ms=0 40ms=3 42ms=2 44ms=2 46ms=1 48ms=0 53ms=4 57ms=0 61ms=0 65ms=1 69ms=0 73ms=1 77ms=0 81ms=2 85ms=0 89ms=0 93ms=2 97ms=1 101ms=3 105ms=0 109ms=0 113ms=0 117ms=0 121ms=0 125ms=0 129ms=0 133ms=1 150ms=3 200ms=1 250ms=2 300ms=2 350ms=1 400ms=0 450ms=0 500ms=0 550ms=0 600ms=0 650ms=0 700ms=0 750ms=0 800ms=0 850ms=0 900ms=0 950ms=0 1000ms=1 1050ms=0 1100ms=0 1150ms=0 1200ms=0 1250ms=0 1300ms=0 1350ms=0 1400ms=0 1450ms=0 1500ms=0 1550ms=0 1600ms=0 1650ms=0 1700ms=0 1750ms=0 1800ms=0 1850ms=0 1900ms=0 1950ms=0 2000ms=0 2050ms=0 2100ms=0 2150ms=0 2200ms=0 2250ms=0 2300ms=0 2350ms=0 2400ms=0 2450ms=0 2500ms=0 2550ms=0 2600ms=0 2650ms=0 2700ms=0 2750ms=0 2800ms=0 2850ms=0 2900ms=0 2950ms=0 3000ms=0 3050ms=0 3100ms=0 3150ms=0 3200ms=0 3250ms=0 3300ms=0 3350ms=0 3400ms=0 3450ms=0 3500ms=0 3550ms=0 3600ms=0 3650ms=0 3700ms=0 3750ms=0 3800ms=0 3850ms=0 3900ms=0 3950ms=0 4000ms=0 4050ms=0 4100ms=0 4150ms=0 4200ms=0 4250ms=0 4300ms=0 4350ms=0 4400ms=0 4450ms=0 4500ms=0 4550ms=0 4600ms=0 4650ms=0 4700ms=0 4750ms=0 4800ms=0 4850ms=0 4900ms=0 4950ms=0

具体可以点击这里

3.5.3SurfaceFlinger 进行监控

截取部分数据

 1picasso:/ $ dumpsys SurfaceFlinger -latency com.miui.home/com.miui.home.launcher.Launcher
 2Build configuration: [sf PRESENT_TIME_OFFSET=0 FORCE_HWC_FOR_RBG_TO_YUV=1 MAX_VIRT_DISPLAY_DIM=4096 RUNNING_WITHOUT_SYNC_FRAMEWORK=0 NUM_FRAMEBUFFER_SURFACE_BUFFERS=3] [libui] [libgui]
 3
 4Display identification data:
 5Display 19260668995500161 (HWC display 0): port=129 pnpId=QCM displayName="xiaomi 37 02 "
 6
 7Wide-Color information:
 8Device has wide color built-in display: 1
 9Device uses color management: 1
10DisplayColorSetting: Unknown 258
11Display 19260668995500161 color modes:
12    ColorMode::NATIVE (0)
13    ColorMode::SRGB (7)
14    ColorMode::DISPLAY_P3 (9)
15    Current color mode: ColorMode::SRGB (7)
16
17Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]
18
19VSYNC configuration:
20         app phase:   1000000 ns                 SF phase:   1000000 ns
21   early app phase:   1000000 ns           early SF phase:   1000000 ns
22GL early app phase:   1000000 ns        GL early SF phase:   1000000 ns
23    present offset:         0 ns             VSYNC period:  20000000 ns
24
25Scheduler enabled.+  Smart 90 for video detection: off

具体可以点击这里

3总结

Choreographer:编舞者,指对CPU/GPU绘制的指导,收到VSync信号才开始绘制,保证绘制拥有完整的16.7ms。通常应用层不会直接使用Choreographer,但是存在Vsync + TripleBuffer + Choreographer 的机制,其就可以提供一个稳定的帧率输出机制,让软件层和硬件层可以以共同的频率一起工作。主要是作为一种承上启下的作用,实质就是通过上层封装,间接去操作socketpair双向通信管道。

承上

负责接收和处理 App 的各种更新消息和回调,等到 Vsync 事件回调(通过 FrameDisplayEventReceiver.onVsync )统一处理。比如集中五种处理 Input(主要是 Input 事件的处理) 、Animation(动画相关)、Traversal(包括 measure、layout、draw 等操作) 等,判断卡顿掉帧情况,记录 CallBack 耗时等

启下

负责请求和申请Vsync的下一帧信号。请求 Vsync(FrameDisplayEventReceiver.scheduleVsync)。

  • 尽量避免在执行动画渲染的前后在主线程放入耗时操作,否则会造成卡顿感,影响用户体验;
  • 可通过Choreographer.getInstance().postFrameCallback()来监听帧率情况;
  • 每调用一次scheduleFrameLocked(),则mFrameScheduled=true,可进入doFrame()方法体内部,执行完doFrame()并设置mFrameScheduled=false;
  • doCallbacks回调方法有4个类别:INPUT(输入事件),ANIMATION(动画),TRAVERSAL(窗口刷新),COMMIT(完成后的提交操作)。

4补充

1.关于mFrameScheduled的bool值

 1//doFrame是处理上一帧的数据,每隔一个Vsync信号,即每隔16.7ms,只处理一次,当然在卡顿的时候并不能保证16.7ms一个信号周期
 2//frameworks/base/core/java/android/view/Choreographer.java#doFrame
 3void doFrame(long frameTimeNanos, int frame) {
 4    synchronized (mLock) {
 5        if (!mFrameScheduled) {
 6            return; // no work to do
 7        }
 8        ...
 9        mFrameScheduled = false;
10    }
11}
12
13//这里的scheduleFrameLocked,使得每次申请下一帧都保持最新的一次事件
14//frameworks/base/core/java/android/view/Choreographer.java#scheduleFrameLocked
15private void scheduleFrameLocked(long now) {
16    if (!mFrameScheduled) {
17        mFrameScheduled = true;
18        ...
19    }
20}

2.这里面涉及到的部分时间梳理

会在Vsync信号篇章中具体展开。

5源码下载

源码下载,点击这里

参考

[1] Gracker, Android 基于 Choreographer 的渲染机制详解, 2019.

[2] 袁辉辉, Choreographer原理, 2017.

[3] lbtrace, Android应用与SurfaceFlinger建立连接的过程, 2019.

[4] 苍耳叔叔, Android-Choreographer原理, 2020.

[5] bug樱樱, 一看就会!Android屏幕刷新机制最新讲解—VSync、Choreographer 全面理解!, 2020.

[6] Drummor, Android 怎么就不卡了呢之Choreographer, 2019.

[7] 丹枫无迹, Choreographer全解析, 2021.

[8] DeltaTech, Android Choreographer 源码分析, 2016.

[9] 静默加载, ViewRootImpl的独白,我不是一个View(布局篇), 2017.

[10] 大苏, Android 屏幕刷新机制, 2018.

[11] 梅花十三儿, [Android禅修之路] 解读Vsync(一), 2022.

[12] Innerpeace_yu, C++中explicit的用法, 2018.

[13] zhengna, Android UI性能测试——使用 Gfxinfo 衡量性能, 2019.

[14] 麻辣小龙虾, 安卓帧率计算方案和背后原理剖析, 2021.

[15] DJLZPP, AndroidQ UI刷新机制详解, 2020.

[16] DJLZPP, AndroidQ 应用层Vsync信号的注册与接收(下), 2020.