• 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,然后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系统》一书

    杨长刚著

    电子工业出版社出版

  • 相关阅读:
    php函数注释
    组件化开发
    7.哪些工具可以帮助查找bug或进行静态分析
    6.Python中内存是如何管理的?
    5.Python是怎么解释的?
    4.pickling 和unpickling是什么?
    3.PEP 8是什么?
    2.Python是什么?使用Python的好处是什么?
    Redis介绍及字符串操作
    字符串转换为二进制
  • 原文地址:https://www.cnblogs.com/broadview/p/2876582.html
Copyright © 2020-2023  润新知