在上一篇Android Project Butter分析中介绍了Android4.1通过引入VSync机制来改善显示效果,并分析了VSync机制的原理。本文主要分析VSync信号的产生过程。VSync信号产生有两种方式,一种是硬件中断产生,另一种是使用软件模拟产生,至于使用何种方式产生VSync信号,就和硬件系统配置有关。在Android4.1以后的版本中,定义了HWComposer硬件抽象模块来负责产生VSync信号。HWComposer硬件抽象层定义:
hardware\libhardware\modules\hwcomposer\hwcomposer.cpp
hwc_module_t HAL_MODULE_INFO_SYM = { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: HWC_HARDWARE_MODULE_ID, name: "Sample hwcomposer module", author: "The Android Open Source Project", methods: &hwc_module_methods, } };注册的硬件抽象模块方法定义如下:
static struct hw_module_methods_t hwc_module_methods = { open: hwc_device_open };
关于为硬件抽象模块HWComposer定义的数据结构之间的关系如下下图所示:
在初始化DisplayHardware对象时,会创建一个HWComposer对象:
void DisplayHardware::init(uint32_t dpy) { ... // initialize the H/W composer mHwc = new HWComposer(mFlinger, *this, mRefreshPeriod); if (mHwc->initCheck() == NO_ERROR) { mHwc->setFrameBuffer(mDisplay, mSurface); } }这里使用SurfaceFlinger,DisplayHardware对象及屏幕刷新周期来构造HWComposer对象,HWComposer的构造过程如下:
frameworks\native\services\surfaceflinger\DisplayHardware\HWComposer.cpp
HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger,EventHandler& handler,nsecs_t refreshPeriod) : mFlinger(flinger), mModule(0), mHwc(0), mList(0), mCapacity(0), mNumOVLayers(0), mNumFBLayers(0), mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE), mEventHandler(handler), mRefreshPeriod(refreshPeriod), mVSyncCount(0), mDebugForceFakeVSync(false) { char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.no_hw_vsync", value, "0"); mDebugForceFakeVSync = atoi(value); //是否需要软件模拟VSync bool needVSyncThread = false; //加载HWComposer硬件抽象模块 int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); if (err == 0) { //打开HWComposer硬件抽象模块 err = hwc_open(mModule, &mHwc); if (err == 0) { //打开成功,注册回调函数 if (mHwc->registerProcs) { mCBContext.hwc = this; mCBContext.procs.invalidate = &hook_invalidate; mCBContext.procs.vsync = &hook_vsync; mHwc->registerProcs(mHwc, &mCBContext.procs); memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero)); } if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) { if (mDebugForceFakeVSync) { // make sure to turn h/w vsync off in "fake vsync" mode mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0); } } else { needVSyncThread = true; } } } else { needVSyncThread = true; } //如果HWComposer硬件抽象模块打开失败或者HWComposer硬件抽象模块的版本小于HWC_DEVICE_API_VERSION_0_3,则采用软件模拟产生VSync信号 if (needVSyncThread) { //创建VSync产生线程VSyncThread mVSyncThread = new VSyncThread(*this); } }
在构造HWComposer对象时,选择了VSync信号产生方式:1.硬件产生;2.软件模拟产生;假如当前系统可以成功加载HWC_HARDWARE_MODULE_ID=hwcomposer,并且通过这个库能顺利打开设备(hwc_composer_device_t),并且其版本号又大于HWC_DEVICE_API_VERSION_0_3的话,我们就采用硬件方式产生VSync,否则需要创建一个新的VSync线程来模拟产生信号。
err = hwc_open(mModule, &mHwc);mModule为hw_module_t类型变量,用于描述hwcomposer硬件抽象模块,参数mHwc的类型为hwc_composer_device_t,该结构用于描述hwcomposer硬件设备。
static inline int hwc_open(const struct hw_module_t* module, hwc_composer_device_t** device) { return module->methods->open(module, HWC_HARDWARE_COMPOSER, (struct hw_device_t**)device); }在定义hwcomposer硬件抽象层时,注册了该硬件抽象模块的打开回调函数hwc_device_open,其实现过程如下:
static int hwc_device_open(const struct hw_module_t* module, const char* name,struct hw_device_t** device) { int status = -EINVAL; if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { struct hwc_context_t *dev; dev = (hwc_context_t*)malloc(sizeof(*dev)); /* initialize our state here */ memset(dev, 0, sizeof(*dev)); /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = hwc_device_close; dev->device.prepare = hwc_prepare; dev->device.set = hwc_set; *device = &dev->device.common; status = 0; } return status; }打开hwcomposer硬件模块过程实际上是创建一个hwc_context_t对象,同时将该模块的回调函数注册到hwc_context_t对象中,如果mHwc->registerProcs不为空的话,我们注册硬件回调mCBContext.procs。当有事件产生时,比如vsync或者invalidate,硬件模块将分别通过procs.vsync和procs.invalidate来通知HWComposer。在这里可以创建一个线程专门负责响应VSync中断:
bool VSyncThread::threadLoop() { { // scope for lock Mutex::Autolock _l(mLock); while (!mEnabled) { mCondition.wait(mLock); } } //进入FrameBuffer驱动等待VSync中断到来 if (ioctl(mFbFd, FBIO_WAITFORVSYNC, NULL) == -1) { ALOGE("fail to wait vsync , mFbFd:%d" , mFbFd); }else{ if(!mDev->procs || !mDev->procs->vsync){ ALOGW("device procs or vsync is null procs:%x , vsync:%x", mDev->procs , mDev->procs->vsync); return true; } //调用VSync回调函数 mDev->procs->vsync(mDev->procs, 0, systemTime(CLOCK_MONOTONIC)); } return true; }在该线程运行过程中通过ioctl系统调用进入到fb驱动等待VSync中断,如果VSync中断到来,则ioctl函数从驱动中返回。同时如果注册了VSync回调处理函数,则调用该回调函数来响应VSync信号。在前面构造HWComposer对象时,我们已经注册了VSync中断回调函数为hook_vsync,该函数的实现如下:
void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp) { reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy, timestamp); }在该函数里调用HWComposer对象的vsync函数来出来响应VSync中断
void HWComposer::vsync(int dpy, int64_t timestamp) { ATRACE_INT("VSYNC", ++mVSyncCount&1); mEventHandler.onVSyncReceived(dpy, timestamp); }mEventHandler为DisplayHardware对象,这里又将VSync中断信号交给DisplayHardware对象处理,DisplayHardware继承于EventHandler类,并实现了该类的虚方法onVSyncReceived,这里调用DisplayHardware对象的onVSyncReceived函数来处理VSync中断信号。关于VSync信号的处理在稍后介绍,到此硬件产生VSync信号的过程就完成了。
HWComposer::VSyncThread::VSyncThread(HWComposer& hwc) : mHwc(hwc), mEnabled(false), mNextFakeVSync(0), mRefreshPeriod(hwc.mRefreshPeriod) { }VSyncThread继承于RefBase类,该对象第一次强引用自动调用onFirstRef()函数,在该函数中启动线程
void HWComposer::VSyncThread::onFirstRef() { run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); }VSyncThread线程的执行过程如下:
bool HWComposer::VSyncThread::threadLoop() { { // scope for lock Mutex::Autolock _l(mLock); while (!mEnabled) {//VSyncThread线程启动后并不立即产生VSync信号,只有通过调用setEnabled函数使能VSync信号后,该线程才往下执行,从而产生VSync信号 mCondition.wait(mLock); } } const nsecs_t period = mRefreshPeriod;//VSync信号的产生间隔时间,屏幕刷新时间 const nsecs_t now = systemTime(CLOCK_MONOTONIC); nsecs_t next_vsync = mNextFakeVSync;//下一次VSync信号产生时间 nsecs_t sleep = next_vsync - now; //需要休眠的时间间隔 if (sleep < 0) { // we missed, find where the next vsync should be sleep = (period - ((now - next_vsync) % period)); next_vsync = now + sleep; } mNextFakeVSync = next_vsync + period; struct timespec spec; spec.tv_sec = next_vsync / 1000000000; spec.tv_nsec = next_vsync % 1000000000; int err; do { err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); } while (err<0 && errno == EINTR); //每隔屏幕刷新时间间隔调用一次onVSyncReceived函数 if (err == 0) { mHwc.mEventHandler.onVSyncReceived(0, next_vsync); } //一次信号产生完成后,函数直接返回true,当threadLoop返回值为“真”时,它将被系统再一次调用,从而循环起来。 return true; }mEnabled用于控制是否产生VSync信号。当希望关闭VSync信号发生源时,调用VSyncThread::setEnabled(false),否则传入true。mEnabled为false时,VSyncThread就处于等待状态,直到再次使能这个线程。
当休眠时间到了后,函数跳出while循环,表示VSync信号产生的时刻到了,这时就调用成员变量mEventHandler的onVSyncReceived函数来响应VSync信号,软件模拟产生VSync信号的间隔时间就是屏幕刷新周期。成员变量mEventHandler的类型为EventHandler,在HWComposer的构造函数中,该变量指向DisplayHardware对象,因此这里调用的是DisplayHardware对象的onVSyncReceived函数来处理VSync中断。这里可以看出,无论是硬件产生VSync还是软件模拟产生VSync信号,最终都是交给DisplayHardware对象处理:
void DisplayHardware::onVSyncReceived(int dpy, nsecs_t timestamp) { sp<VSyncHandler> handler; { // scope for the lock Mutex::Autolock _l(mLock); mLastHwVSync = timestamp; if (mVSyncHandler != NULL) { handler = mVSyncHandler.promote(); } } if (handler != NULL) { handler->onVSyncReceived(dpy, timestamp); } }
void EventThread::onFirstRef() { mHw.setVSyncHandler(this); ... }
void DisplayHardware::setVSyncHandler(const sp<VSyncHandler>& handler) { Mutex::Autolock _l(mLock); mVSyncHandler = handler; }
void EventThread::onVSyncReceived(int, nsecs_t timestamp) { Mutex::Autolock _l(mLock); mVSyncTimestamp = timestamp; mCondition.broadcast(); }