EventThread线程对VSync的接收
EventThread线程对VSync的接收
EventThread被设计用来接收VSync事件通知,并分发VSync通知给系统中的每一个感兴趣的注册者。VSync来源自底层硬件驱动程序的上报,对于Android能看到的接口来说,它是来自HAL层的hwc_composer_device的抽象硬件设备。若硬件不支持,则HWComposer会创建一个线程去模拟产生VSync事件通知。一旦工作起来,VSync将像一个脉搏一样,不断通知到Surfaceflinger中的EventThread线程,由后者再分发给感兴趣的注册者。
先来看一下EventThread何时被创建并开始运行的。
在SurfaceFlinger类被创建时,它的onFirstRef函数将被调用(因为最终继承自RefBase),代码如下:
因为SurfaceFlinger继承自线程类Thread(上面的行130)调用了run函数,意味着创建一个新线程的执行。它的过程是:Thread::run将创建一个新线程,名称为SurfaceFlinger(后面我们将称之为SurfaceFlinger线程),线程的入口函数Thread::_threadLoop又将调用子类重载的threadLoop函数,不过在调用重载的threadLoop之前,先调用子类重载的readyToRun(只是初次时)。也就是说,此处的run函数调用将启动一个新线程SurfaceFlinger,然后SurfaceFlinger的readyToRun函数在其里面被调用,从而做一些初始化工作,如前面提到的从ashm分配一块共享控制块surface_flinger_cblk_t,见前面的11.5.2小节。
在SurfaceFlinger的readyToRun函数的后面,将会创建EventThread线程(下面的行300):
在其EventThread的onFirstRef中被要求开始执行,见行52(参见文件EventThread.cpp):
这样,EventThead在创建后,马上开始了它的线程循环。
再来看一下HAL层是如何向EventThread发送VSync通知的。
在HAL层的文件hardware/libhardware/include/hwcomposer.h中定义了一个供底层向上调用的回调例程hwc_procs结构体,它包含两个例程函数:invalidate和vsync。代码如下(见文件hwcomposer.h):
在Android的HWComposer.h中定义了两个结构体:回调callbacks和回调上下文cb_context。其中callbacks继承自上面的hwc_procs,代码如下:
在HWComposer的构造函数中,先从库中解析符号,然后打开HWComposer硬件模块(下面的行00063),再根据其open函数打开HAL抽象硬件设备mHwc(下面的行00066),然后再判断硬件设备mHwc是否支持registerProcs函数(下面的行00070)。若硬件平台厂商实现了该函数,并在open函数中将其赋值给了HAL抽象硬件设备hwc_composer_device的registerProcs成员,则该成员不为空,表示支持上述的回调例程hwc_procs。HWComposer的构造函数将依据此来判断是否支持VSync,代码如下(参见文件HWComposer.cpp):
在硬件平台支持VSync的情况下,通过上面的行00072~00073的赋值和行00074的注册回调例程,来自底层HAL的调用,将转到调用钩子函数hook_xxx。其中回调例程hwc_procs中的VSync将指向hook_vsync钩子函数,后者代码如下(参见文件HWComposer.cpp):
它又调用到下面的VSync成员函数(参见文件HWComposer.cpp):
上面行00125的mEventHandler实际为DisplayHardware对象。在HWComposer中,定义了一个抽象接口EventHandler,并维护了一个EventHandler类型的对象引用;而DisplayHardware实现了该接口,并在DisplayHardware的init函数初始化时,创建了HWComposer对象,将其指定给了HWComposer维护的EventHandler对象引用(即mEventHandler,见上面HWComposer构造函数的行00048)。因此,对VSync的调用将调用到DisplayHardware的onVSyncReceived函数,后者的代码如下(参见文件DisplayHardware.cpp):
这将继续调用到DisplayHardware中维护的一个handler,而这个handler实际是EventThread的对象(见EventThread::onFirstRef函数,在该函数中指定)。因此,对VSync的调用实际调用到下面的EventThread的onVSyncReceived成员函数(见EventThread.cpp):
这将唤醒EventThread线程的循环函数threadLoop在Condition上的睡眠等待。
EventThread的线程循环函数threadLoop主要用于向系统中对VSync感兴趣的注册者分发VSync事件通知,下节将对其做详细介绍。
对于不支持VSync上报通知的硬件平台来说,则HWComposer会创建一个VSyncThread线程,用于模拟VSync的发送。在HWComposer构造函数的后面,判断出需要模拟一个VSync线程后即创建该线程(下面的行92),代码如下:
VSyncThread的线程循环函数threadLoop后面的部分代码如下(参见文件HWComposer.cpp):
上面的行318睡眠片刻,醒来后即模拟发送VSync事件通知(行322)。睡眠的时间最终由HWComposer中的刷新率变量mRefreshPeriod确定,该值来自framebuffer device或系统设置信息,mRefreshPeriod在HWComposer的构造函数中被赋值,见前面其构造函数的代码行55中。如图11-21所示,VSync起源于①,经过一步步调用,执行到②,唤醒可能正在睡眠的线程,然后由线程循环函数去分发它。图中①到②是本小节讲述的,②后面的将在下一小节讲述。
图11‑21 EventThread接收和分发VSync示意图
本文节选自《深入剖析Android系统》一书
杨长刚著
电子工业出版社出版