Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1531168
  • 博文数量: 465
  • 博客积分: 8915
  • 博客等级: 中将
  • 技术积分: 6365
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-30 15:05
文章分类

全部博文(465)

文章存档

2017年(33)

2016年(2)

2015年(4)

2014年(29)

2013年(71)

2012年(148)

2011年(178)

分类: Android平台

2013-01-25 14:19:17

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,然后SurfaceFlingerreadyToRun函数在其里面被调用,从而做一些初始化工作,如前面提到的从ashm分配一块共享控制块surface_flinger_cblk_t,见前面的11.5.2小节。

SurfaceFlingerreadyToRun函数的后面,将会创建EventThread线程(下面的行300):


在其EventThreadonFirstRef中被要求开始执行,见行52(参见文件EventThread.cpp):


这样,EventThead在创建后,马上开始了它的线程循环。

再来看一下HAL层是如何向EventThread发送VSync通知的。

HAL层的文件hardware/libhardware/include/hwcomposer.h中定义了一个供底层向上调用的回调例程hwc_procs结构体,它包含两个例程函数:invalidatevsync。代码如下(见文件hwcomposer.h):

AndroidHWComposer.h中定义了两个结构体:回调callbacks和回调上下文cb_context。其中callbacks继承自上面的hwc_procs,代码如下:


HWComposer的构造函数中,先从库中解析符号,然后打开HWComposer硬件模块(下面的行00063),再根据其open函数打开HAL抽象硬件设备mHwc(下面的行00066),然后再判断硬件设备mHwc是否支持registerProcs函数(下面的行00070)。若硬件平台厂商实现了该函数,并在open函数中将其赋值给了HAL抽象硬件设备hwc_composer_deviceregisterProcs成员,则该成员不为空,表示支持上述的回调例程hwc_procsHWComposer的构造函数将依据此来判断是否支持VSync,代码如下(参见文件HWComposer.cpp):


在硬件平台支持VSync的情况下,通过上面的行0007200073的赋值和行00074的注册回调例程,来自底层HAL的调用,将转到调用钩子函数hook_xxx。其中回调例程hwc_procs中的VSync将指向hook_vsync钩子函数,后者代码如下(参见文件HWComposer.cpp):


它又调用到下面的VSync成员函数(参见文件HWComposer.cpp):


上面行00125mEventHandler实际为DisplayHardware对象。在HWComposer中,定义了一个抽象接口EventHandler,并维护了一个EventHandler类型的对象引用;而DisplayHardware实现了该接口,并在DisplayHardwareinit函数初始化时,创建了HWComposer对象,将其指定给了HWComposer维护的EventHandler对象引用(即mEventHandler,见上面HWComposer构造函数的行00048)。因此,对VSync的调用将调用到DisplayHardwareonVSyncReceived函数,后者的代码如下(参见文件DisplayHardware.cpp):


这将继续调用到DisplayHardware中维护的一个handler,而这个handler实际是EventThread的对象(见EventThread::onFirstRef函数,在该函数中指定)。因此,对VSync的调用实际调用到下面的EventThreadonVSyncReceived成员函数(见EventThread.cpp:


这将唤醒EventThread线程的循环函数threadLoopCondition上的睡眠等待。

EventThread的线程循环函数threadLoop主要用于向系统中对VSync感兴趣的注册者分发VSync事件通知,下节将对其做详细介绍。

对于不支持VSync上报通知的硬件平台来说,则HWComposer会创建一个VSyncThread线程,用于模拟VSync的发送。在HWComposer构造函数的后面,判断出需要模拟一个VSync线程后即创建该线程(下面的行92),代码如下:


VSyncThread的线程循环函数threadLoop后面的部分代码如下(参见文件HWComposer.cpp):


上面的行318睡眠片刻,醒来后即模拟发送VSync事件通知(行322)。睡眠的时间最终由HWComposer中的刷新率变量mRefreshPeriod确定,该值来自framebuffer device或系统设置信息,mRefreshPeriodHWComposer的构造函数中被赋值,见前面其构造函数的代码行55中。如图11-21所示,VSync起源于①,经过一步步调用,执行到②,唤醒可能正在睡眠的线程,然后由线程循环函数去分发它。图中①到②是本小节讲述的,②后面的将在下一小节讲述。


11?21 EventThread接收和分发VSync示意图




本文节选自《深入剖析Android系统》一书

杨长刚著

电子工业出版社出版


阅读(2247) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~