From: http://blog.chinaunix.net/uid-13164110-id-3481832.html

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系统》一书

杨长刚著

电子工业出版社出版


更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. 使用Handler在子线程中更新UI
  3. [Fuzz]Android模糊测试
  4. usb 网络共享无法选择
  5. JNI和NDK编程(一)
  6. Android桌面小控件appwidget的故事Ⅰ
  7. Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
  8. android JNI实验心得
  9. 安卓学习笔记(十)服务Service

随机推荐

  1. Android流式布局实现
  2. 在Android平台上实现条型码扫描与识别
  3. Android布局中的常用属性小结
  4. 三星平台 android audio 架构探讨点滴积
  5. Android问题(一)Android(安卓)Studio 提示"
  6. Android2.3发布
  7. NDK编译Android字符界面的可执行程序
  8. 【Android】自定义控件之View原理与使用
  9. Android(安卓)2.2新增Widget之ProtipWidg
  10. Hello, Android!