Android垂直同步信号VSync的产生及传播结构详解

1 垂直同步信号

VSync(即V-Sync垂直同步)的具体含义和用途文章不细说,看下图的VSync的位置大致也就知道它的用途(简单理解成是硬件定时中断貌似也可以,周期性的硬件中断,频率为60Hz,周期为0.0167s,也就是16ms)。
本文主要关注以下几个问题:
(1)VSync是如何产生的?
(2)VSync最初是在哪个进程中捕获的?
(3)VSync是如何分发到各个应用进程的?
(4)view.invalidate是如何与VSync配合,从而实现重绘的?
下面的图片就不仔细介绍了

2 SurfaceFlinger进程

以前的Android系统中SurfaceFlinger是在System_Server进程中的,但是自从Android4.x(x具体是几,没细查)开始SurfaceFlinger已经开始作为一个独立的进程存在,具体的进程入口在Main_surfaceflinger.cpp文件的main函数中,简单看一下这个函数:

   int main(int, char**) {
    signal(SIGPIPE, SIG_IGN);
    // When SF is launched in its own process, limit the number of
    // binder threads to 4. 设置线程池最多只能有4个Binder线程
    ProcessState::self()->setThreadPoolMaxThreadCount(4);

    //创建进程的ProcessState对象,打开binder设备,同时创建并映射一部分Binder共享内存
    sp<ProcessState> ps(ProcessState::self());

    //开启Binder线程,里面会有循环不断的talkWithDriver
    ps->startThreadPool();

    // instantiate surfaceflinger 
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();

    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);    //设置surfaceflinger进程的优先级

    set_sched_policy(0, SP_FOREGROUND);

    // initialize before clients can connect
    flinger->init();   //初始化 SurfaceFlinger 对象

    // publish surface flinger
    //返回的sm是一个BpServiceManager对象,相当于是new BpServiceManager(new BpBinder(0))
    sp<IServiceManager> sm(defaultServiceManager());

    //BpServiceManager向service_manager守护进程注册当前的SurfaceFlinger服务,里面传进来了SurfaceFlinger对象flinger
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

    // run in this thread
    flinger->run(); 
    return 0;
} 

相关的注释上面都有,SurfaceFlinger作为核心服务还是很复杂的,里面涉及到的东西太多了。看一下SurfaceFlinger.init函数(SurfaceFlinger.cpp):
这里写图片描述
与垂直同步信号相关的关键代码是截图中的最后一行:

mHwc = new HWComposer(this,*static_cast<HWComposer::EventHandler *>(this));   

里面给的两个参数其实都是指向SurfaceFlinger对象本身,记住这一点,继续往下。

2.1 分析HWComposer

代码在HWComposer.h HWComposer.cpp中,分析C++代码和Java代码有一点很大的区别,同样是类的成员变量,C++成员变量很多都是实际的对象(至于是栈对象还是堆对象,要看外部对象是直接创建的栈对象,还是new创建的堆对象),而Java代码里面的成员一定要在new对象以后才有实际的实体,看一下HWComposer的成员变量:

    sp<SurfaceFlinger>              mFlinger;   //指针
    framebuffer_device_t*           mFbDev;     //指针
    structhwc_composer_device_1*   mHwc;       //指针
    structhwc_display_contents_1*  mLists[MAX_HWC_DISPLAYS];         //指针数组
    DisplayData                     mDisplayData[MAX_HWC_DISPLAYS];   //DisplayData对象数组
    mutable Mutex mDisplayLock;              //锁对象
    size_t                          mNumDisplays;
    cb_context*                     mCBContext;      //指针
    EventHandler&                   mEventHandler;   //引用
    size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
    sp<VSyncThread>                 mVSyncThread;    //指针
    bool                            mDebugForceFakeVSync;
    BitSet32                        mAllocatedDisplayIDs;   //对象
    mutable Mutex  mLock;         //锁对象
    mutable nsecs_t  mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
    mutable Mutex  mEventControlLock;  //锁对象

上面这一点在分析C++代码的时候要尤其注意,看一下HWComposer的构造函数:

HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, EventHandler& handler)
    : mFlinger(flinger),
      mFbDev(0), mHwc(0), mNumDisplays(1),   //初始情况下mHwc是一个空指针
      mCBContext(new cb_context),            //这里新创建了一个cb_context对象
      mEventHandler(handler),
      mDebugForceFakeVSync(false)
{ 
    bool needVSyncThread = true; 
    .....
    // Note: some devices may insist that the FB HAL be opened before HWC. 尝试打开硬件HWC
    int fberr = loadFbHalModule();
    loadHwcModule();  //加载HWC模块,若打开成功,则mHwc将不为空
    .......
    if (mHwc) {
        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
              (hwcApiVersion(mHwc) >> 24) & 0xff,
              (hwcApiVersion(mHwc) >> 16) & 0xff);
        if (mHwc->registerProcs) {
            mCBContext->hwc = this;
            mCBContext->procs.invalidate = &hook_invalidate;
            mCBContext->procs.vsync = &hook_vsync;   //硬件产生中断,通过hook_vsync函数进行同步信号的通知
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                mCBContext->procs.hotplug = &hook_hotplug;
            else
                mCBContext->procs.hotplug = NULL;
            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
            mHwc->registerProcs(mHwc, &mCBContext->procs);
        }

        // don't need a vsync thread if we have a hardware composer  存在硬件同步信号发生器,就不需要软件模拟线程
        needVSyncThread = false;
    }
    ............ 
    if (needVSyncThread) { //设备不支持硬件HWC,用软件模拟同步信号,这里不讨论,整个的流程还是一样的
        // we don't have VSYNC support, we need to fake it
        mVSyncThread = new VSyncThread(*this);
    }
}

上面的代码首先执行参数初始化表,根据前面的记录,这里的mFlinger和mEventHandler指向的都是前面的SurfaceFlinger对象, 然后加载HWC模块,实际上对应的是一个so库,读取到里面的相关信息后,设置了里面的产生硬件同步信号时候的回调函数是hook_vsync,这里就是将产生硬件同步信号时相应的函数入口存储到HWC模块的相关结构中,看一下hook_vsync函数的声明和定义:
声明:

    static void hook_invalidate(conststructhwc_procs* procs);   
    static void hook_vsync(conststructhwc_procs* procs, int disp,int64_t timestamp);   
    static void hook_hotplug(conststructhwc_procs* procs, int disp, int connected);

只有static类型的函数可以作为回调函数将函数名称作为参数直接传递,这是因为static函数不需要依赖对象的this指针,相应的函数地址在编译期间即可确定。
定义:

void HWComposer::hook_vsync(conststruct hwc_procs* procs, int disp, int64_t timestamp) {
    cb_context* ctx = reinterpret_cast<cb_context*>(const_cast<hwc_procs_t*>(procs));
    ctx->hwc->vsync(disp, timestamp);
}

注意看上面HWComposer构造器中被标红的几行,里面的ctx->hwc指向的就是当前的this指针,也就是当前的对象,因此调用的就是当前对象的vsync函数,看一下这个函数:

void HWComposer::vsync(int disp, int64_t timestamp) {
    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
        {
            Mutex::Autolock _l(mLock);

            // There have been reports of HWCs that signal several vsync events
            // with the same timestamp when turning the display off and on. This
            // is a bug in the HWC implementation, but filter the extra events
            // out here so they don't cause havoc downstream.
            mLastHwVSync[disp] = timestamp;   //记录编号为disp的显示设备的sync时间
        }
        char tag[16];
        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1); 
       //HWC以及VSyncThread软件模拟,最终都是通过mEventHandler.onVSyncReceived函数将同步信号发出去的
        mEventHandler.onVSyncReceived(disp, timestamp);
    }
}

最重要的就是调用了mEventHandler.onVSyncReceived()函数,前面分析到,这里mEventHandler实际上就是创建当前HWComposer对象的SurfaceFlinger对象,因此会调用SurfaceFlinger.onVSyncReceived()函数,经过上面的一启动过程,HWC硬件产生的同步信号就可以到达SurfaceFlinger里面了。

2.2 SurfaceFlinger分发vsync

先看一下mPrimaryHWVsyncEnabled这个成员变量,初始情况下是false,实际经过下面的调用后会变成true:
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
    bool needsHwVsync = false; 
    { // Scope for the lock
        Mutex::Autolock _l(mHWVsyncLock);
        if (type == 0 && mPrimaryHWVsyncEnabled) {
            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
        }
    } 
    if (needsHwVsync) {
        enableHardwareVsync();
    } else {
        disableHardwareVsync(false);
    }
}

这里的type实际上就是DisplayDevice的类型,上面的设置的时候就是DisplayDevice::DISPLAY_PRIMARY,这个值就是0,上面分析mPrimaryHWVsyncEnabled是true,因此会调用到mPrimaryDispSync.addResyncSample函数,至于下面的if判断就没有必要看了,里面enableHardwareVsync的时候若mPrimaryHWVsyncEnabled=true就直接返回了,看一下变量和mPrimaryDispSync.addResyncSample函数:
这里写图片描述
这里mPrimaryDispSync是一个DispSync对象,看一下构造函数:

DispSync::DispSync() : mRefreshSkipCount(0), mThread(new DispSyncThread()) {
    mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); 
    reset();
    beginResync(); .....
}

这里面最重要的就是创建了一个DispSyncThread线程,然后立马运行,根据C++层的线程模型,线程对象一旦运行后,会反复调用线程对象的threadLoop函数,因此这个线程一直运行DispSyncThread.threadLoop函数:

   virtual bool threadLoop() {
        while (true) {
            Vector<CallbackInvocation> callbackInvocations; 
            nsecs_t targetTime = 0;
            { // Scope for lock
                Mutex::Autolock lock(mMutex); 
                bool isWakeup = false; 
                if (now < targetTime) {
                    err = mCond.waitRelative(mMutex, targetTime - now);
                } 
                now = systemTime(SYSTEM_TIME_MONOTONIC);  
                callbackInvocations = gatherCallbackInvocationsLocked(now);
            }
            if (callbackInvocations.size() > 0) {
                fireCallbackInvocations(callbackInvocations);
            }
        } 
        returnfalse;
    }

继续看上面的DispSync.addResyncSample函数:
里面的主要函数调用如下:
DispSync.addResyncSample—–>DispSync.DispSyncThread.updateModel,看一下updateModel函数,里面主要唤醒了在mCond变量上被阻塞的线程:
这里写图片描述
DispSyncThread.threadLoop函数然后执行gatherCallbackInvocationsLocked,从mEventListeners中收集所有满足时间条件的EventListener,然后在fireCallbackInvocations中调用:

    void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
        for (size_t i = 0; i < callbacks.size(); i++) {
            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
        }
    }

可见fireCallbackInvocations函数调用了各个监听器的onDispSyncEvent函数。
经过上述分析可知,SurfaceFlinger接收到HWC的垂直同步信号后,调用SurfaceFlinger.onVSyncReceived()将VSync分发给了SurfaceFlinger.mPrimaryDispSync,SurfaceFlinger.mPrimaryDispSync调用了mEventListeners中所有满足条件的listener,下面就看这些listener是如何注册到SurfaceFlinger.mPrimaryDispSync.mEventListeners里面的。

2.3 DispSyncSource

上面讲到是分发给了SurfaceFlinger.mPrimaryDispSync,继续看一下SurfaceFlinger.init函数:
    // start the EventThread
    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app");
    mEventThread = new EventThread(vsyncSrc);
    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf");
    mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread);

里面创建了两个EventThread对象,并且创建的时候给的参数是一个包装了上述mPrimaryDispSync的DispSyncSource对象,简单看一下DispSyncSource里面的函数,里面有戏,这里先不分析DispSyncSource,先分析EventThread和mEventQueue相关的内容,根据前面的经验,一般Thread类主要看3个方法:构造器、onFirstRef以及threadLoop方法,对应各自的主要功能如下:
(1)EventThread的构造器:设置mVSyncEvent[type]中各个变量属性,后面分析threadLoop相关方法的时候需要参照;
(2)onFirstRef:为什么需要分析这个方法呢?这个方法纯粹是sp指针会用到,一时给忘了暂时先略过,可以认为构造器运行结束这个方法就会执行,这个函数调用了EventThread.run;
(3)threadLoop:线程循环

// This will return when  注释说:当线程开始等待时,这个函数在获取到vsync同步事件并且至少有一个连接对该同步信号感兴趣的时候才会返回
//(1) a vsync event has been received, and
//(2) there was at least one connection interested in receiving it when we started waiting.
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(DisplayEventReceiver::Event* event){
    Mutex::Autolock _l(mLock);
    Vector< sp<EventThread::Connection> > signalConnections; 
    do {
        bool eventPending = false;
        bool waitForVSync = false; 
        size_t vsyncCount = 0;
        nsecs_t timestamp = 0;

        //初始情况下下面的for循环结束后timestamp还是0
        for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
            timestamp = mVSyncEvent[i].header.timestamp;    //参照EventThread的构造器,初始为0
            if (timestamp) {              
                // we have a vsync event to dispatch
                *event = mVSyncEvent[i];              //注意这里将mVSyncEvent[i]复制完后,就将里面的timestamp重新设置成0
                mVSyncEvent[i].header.timestamp = 0;
                vsyncCount = mVSyncEvent[i].vsync.count;
                break;
            }
        }
        //初始情况下下面的for循环结束后timestamp还是0,这里的mPendingEvents也是空的
        if (!timestamp) {
            // no vsync event, see if there are some other event
            eventPending = !mPendingEvents.isEmpty();
            if (eventPending) {
                // we have some other event to dispatch
                *event = mPendingEvents[0];
                mPendingEvents.removeAt(0);
            }
        }

        // find out connections waiting for events  初始情况下下面的for循环结束后timestamp还是0,这里的mPendingEvents也是空的,下面的mDisplayEventConnections也是空的
        size_t count = mDisplayEventConnections.size();
        for (size_t i=0 ; i<count ; i++) {
            sp<Connection> connection(mDisplayEventConnections[i].promote());
            ........//后面再列出
        }  
        ....... 
        // note: !timestamp implies signalConnections.isEmpty(), because we
        // don't populate signalConnections if there's no vsync pending
        if (!timestamp && !eventPending) {
            // wait for something to happen
            if (waitForVSync) {
                ......
                }
            } else {

           //如果当前EventThread线程没有任何Connection连接,这里会进入休眠状态,不再接收同步信号,注意看EventThread::Connection::onFirstRef(),
           //该函数里面会调用EventThread::registerDisplayEventConnection,也就是一旦新建了Connection连接,立马会调用mCondition.broadcast()尝试
           //唤醒处于休眠状态的EventThread线程,开始监听同步信号,并在下次接收到同步信号后转发给Connection连接的对象

                // Nobody is interested in vsync, so we just want to sleep.
                // h/w vsync should be disabled, so this will wait until we
                // get a new connection, or an existing connection becomes
                // interested in receiving vsync again.
                mCondition.wait(mLock);    //初始情况下,直接到这里被挂起了
            }
        }
    } while (signalConnections.isEmpty());

    // here we're guaranteed to have a timestamp and some connections to signal
    // (The connections might have dropped out of mDisplayEventConnections
    // while we were asleep, but we'll still have strong references to them.)
    return signalConnections;
}

初始情况下,进入到了mCondition.wait(mLock);的状态下,直接被挂起了,这时候假设mCondition被解锁,要想结束当前的do{…}while;循环,signalConnections必须不为空,也就是mDisplayEventConnections必须有连接在里面,SF创建完EventThread保存在mSFEventThread里面,继续看SurfaceFlinger.init函数里面的mEventQueue.setEventThread(mSFEventThread):

void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
    mEventThread = eventThread;
    mEvents = eventThread->createEventConnection();
    mEventTube = mEvents->getDataChannel();
    mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, this);
}

里面首先调用上面mSFEventThread线程的createEventConnection方法:

sp<EventThread::Connection> EventThread::createEventConnection() const {
    returnnew Connection(const_cast<EventThread*>(this));
}

这里创建了一个EventThread::Connection对象,看一下:

classEventThread : public Thread, privateVSyncSource::Callback {

    classConnection : public BnDisplayEventConnection {    //这个Connection还是一个Binder机制的服务端,对应BnDisplayEventConnection 
    public:
        Connection(const sp<EventThread>& eventThread);
        status_t postEvent(const DisplayEventReceiver::Event& event);

        // count >= 1 : continuous event. count is the vsync rate
        // count == 0 : one-shot event that has not fired
        // count ==-1 : one-shot event that fired this round / disabled
        int32_t count;

    private:
        virtual~Connection();
        virtualvoidonFirstRef();
        virtual sp<BitTube> getDataChannel() const;
        virtualvoidsetVsyncRate(uint32_t count);
        virtualvoidrequestNextVsync();    // asynchronous
        sp<EventThread> constmEventThread;
        sp<BitTube> constmChannel;
    };
} 

再看一下构造函数:

EventThread::Connection::Connection(
        const sp<EventThread>& eventThread)
    : count(-1), mEventThread(eventThread), mChannel(new BitTube())    //初始情况下count=-1  这里的mChannel是一个BitTube对象
{
} 
void EventThread::Connection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us 
    //向当前线程注册自己这个连接,会将新的连接添加到mDisplayEventConnections里面
    mEventThread->registerDisplayEventConnection(this);
}

先看这个onFirstRef函数,里面调用到了前面传件来的mSFEventThread对象的registerDisplayEventConnection方法,看一下:

status_t EventThread::registerDisplayEventConnection(const sp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    mDisplayEventConnections.add(connection);
    mCondition.broadcast();
    return NO_ERROR;
}

这里写图片描述
上面的注释写的很清楚:
count>=1: 持续的接收事件,count代表接收垂直同步信号的频率,也就是每隔count个垂直同步信号接收一次;
count=0 : 一锤子买卖,只接收一次同步信号;
count=-1: 同样是一锤子买卖,但是已经被处理了,初始的默认值;

这里将刚才创建的EventThread::Connection对象加到了mSFEventThread.mDisplayEventConnections里面,再看EventThread::waitForEvent:

        size_t count = mDisplayEventConnections.size();
        for (size_t i=0 ; i<count ; i++) {
            sp<Connection> connection(mDisplayEventConnections[i].promote());
            if (connection != NULL) {
                bool added = false;
                if (connection->count >= 0) {    // >=0 代表当前的Connection需要接收同步信号
                    waitForVSync = true;
                    if (timestamp) {             // timestamp 初始情况是0,也就是初始情况是不会加到signalConnections里面的
                        if (connection->count == 0) {
                            // fired this time around
                            connection->count = -1;
                            signalConnections.add(connection);
                            added = true;
                        } else if (connection->count == 1 ||
                                (vsyncCount % connection->count) == 0) {
                            // continuous event, and time to report it
                            signalConnections.add(connection);
                            added = true;
                        }
                    }
                }
                if (eventPending && !timestamp && !added) {
                    signalConnections.add(connection);
                }
            } else {
                // we couldn't promote this reference, the connection has
                // died, so clean-up!
                mDisplayEventConnections.removeAt(i);
                --i; --count;
            }
        }
       //注意看这里的注释,下面这个判断主要是用于使能或者是停止同步信号的分发      
       // Here we figure out if we need to enable or disable vsyncs
        if (timestamp && !waitForVSync) {
            // we received a VSYNC but we have no clients
            // don't report it, and disable VSYNC events  
           //接收到了同步信号,但是该线程目前没有任何的客户端,所以不需要进行分发信号,同时停止监听同步信号          
            disableVSyncLocked();
        } else if (!timestamp && waitForVSync) {  //初始情况创建完Connection调用registerDisplayEventConnection注册以后,会走到这里
            enableVSyncLocked();
        }

看一下enableVSyncLocked这个函数:

void EventThread::enableVSyncLocked() {
    //这里的mVSyncSource实际上是一个DispSyncSource对象,调用SF.DispSyncSource.setVSyncEnabled(true)会调用DispSync.addEventListener将
    //当前EventThread注册的同步信号的监听器添加到DispSync
    if (!mUseSoftwareVSync) {   //这里用的是硬件垂直信号
        // never enable h/w VSYNC when screen is off
        if (!mVsyncEnabled) {
            mVsyncEnabled = true;
            mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
            mVSyncSource->setVSyncEnabled(true);
        }
    }
    mDebugVsyncEnabled = true;
    sendVsyncHintOnLocked();
}

这里的mVSyncSource是SurfaceFlinger::DispSyncSource,因此接下来调用的是SurfaceFlinger::DispSyncSource.setCallback和setVSyncEnabled函数:

    virtual void setVSyncEnabled(bool enable) {
        Mutex::Autolock lock(mVsyncMutex);
        if (enable) {
            status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast<DispSync::Callback*>(this));
        } else {
            status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));
        }
        mEnabled = enable;
    }

    virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
        Mutex::Autolock lock(mCallbackMutex);
        = callback;
    }

先将EventThread对象的this指针转换为基类VSyncSource::Callback指针,对应的是onVSyncEvent函数,也就是这里的SurfaceFlinger::DispSyncSource.mCallback可以直接认为对应的是EventThread.onVSyncEvent函数,再看一下setVSyncEnabled函数,调用了DispSync.addEventListener函数:

status_t DispSync::addEventListener(nsecs_t phase,
        const sp<Callback>& callback) {

    Mutex::Autolock lock(mMutex);
    return mThread->addEventListener(phase, callback);
}

下面调用到DispSync::DispSyncThread.addEventListener函数:

    status_t addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
        Mutex::Autolock lock(mMutex);
        for (size_t i = 0; i < mEventListeners.size(); i++) {
            if (mEventListeners[i].mCallback == callback) {
                return BAD_VALUE;
            }
        }
        EventListener listener;
        listener.mPhase = phase;
        listener.mCallback = callback;
        listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / 2; 
        mEventListeners.push(listener); 
        mCond.signal();
        return NO_ERROR;
    }

根据前面的分析可以知道:

HWComposer(产生VSync)--->SurfaceFlinger.onVSyncReceived
--->DispSync.updateModelLocked-->DispSyncThread.updateModel
--->回调所有注册的监听器的onDispSyncEvent函数

现在信号的传递就变成mEventListeners.mCallback.onDispSyncEvent(这里调用的是SurfaceFlinger.DispSyncSource.onDispSyncEvent函数),看一下这个函数:

    virtual void onDispSyncEvent(nsecs_t when) {
        sp<VSyncSource::Callback> callback;
        {
            Mutex::Autolock lock(mCallbackMutex);
            callback = mCallback;
        }
        if (callback != NULL) {
            callback->onVSyncEvent(when);
        }
    }

很显然直接调用了SurfaceFlinger.DispSyncSource.mCallback回调函数,根据上面的分析可知,这个会调用到EventThread.onVSyncEvent函数:

void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    mVSyncEvent[0].header.id = 0;
    mVSyncEvent[0].header.timestamp = timestamp;
    mVSyncEvent[0].vsync.count++;
    mCondition.broadcast();
}

里面主要是会调用到mCondition.broadcast()唤醒正在waitForEvent的EventThread线程,最终会继续执行EventThread的threadLoop函数:

bool EventThread::threadLoop() { 
    DisplayEventReceiver::Event event;
    Vector< sp<EventThread::Connection> > signalConnections;
    //在这里会被阻塞,然后在onVSyncEvent函数中的mCondition.broadcast()中被唤醒
    signalConnections = waitForEvent(&event); 
    // dispatch events to listeners...
    const size_t count = signalConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        const sp<Connection>& conn(signalConnections[i]);
        status_t err = conn->postEvent(event);
    }
    return true;
}

接下来最主要的是调用了connnection->postEvent,这个函数经过一下步骤:
(1)DisplayEventReceiver::sendEvents
(2)BitTube::sendObjects
(3)BitTube::write
最终调用到了BitTube::write函数,其中当前的BitTube对象就是在创建EventThread::Connection时创建的,看一下BitTube::write函数

ssize_t BitTube::write(void const* vaddr, size_t size)
{
    ssize_t err, len;
    do {
        len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
        err = len < 0 ? errno : 0;
    } while (err == EINTR);
    return err == 0 ? len : -err;
}

这样就将垂直同步信号经过socket发送到了连接的另一端,后面将继续分析SurfaceFlinger与应用进程是如何使用这条垂直信号的通路的。

2.4相关的对象

组合:
(1)SurfaceFlinger、HWComposwer
(2)DispSync、DispSyncThread
(3)DispSyncSource、EventThread、Connection
这些组合之间存在比较紧密的联系,下面总结的时候会画出它们之间的相互关系,总体来说:
组合(1):负责系统HWC硬件的启动,以及最原始的VSync信号的捕获;
组合(2):SF将捕获到的信号封装在DispSync里面(VSync信号源),DispSync通过内置的线程进行分发;
组合(3):SF创建的分支信号源(Android创建了两个分支EventThread线程),都是从DispSync(VSync信号源)里面分流出来的(DispSync将同步信号分发给DispSyncSource,DispSyncSource转发给EventThread,总体认为是一次分发),EventThread收到同步信号后分别负责将同步信号进行二次分发;

3 VSync信号的产生与传播

3.1 总结

看图,总结一下:
这里写图片描述
(1)在SF的init函数里面会创建一个HWComposer对象,该对象会打开HWC设备,并将HWComposer::hook_vsync作为HWC产生VSync信号的回调函数;
(2)HWComposer::hook_vsync会将VSync信号传递到SF.onVSyncReceived函数中;
(3)SF.onVSyncReceived函数调用DispSync.addResyncSample(DispSync可以认为是经过SF封装过的垂直同步信号的信号源)函数唤醒DispSync中的守护线程DispSyncThread;
(4)DispSyncThread.fireCallbackInvocations会将VSync信号分发到所有注册到DispSync.mEventListeners中满足条件的监听器的onDispSyncEvent函数中;
从上面的4个步骤可知,所有的VSync信号都是从DispSyncThread真正分发出去的(包括SF进程和所有的应用进程)。
(5)注册到DispSync中的回调由 (DispSyncSource, EventThread)二元组 组成,这两个是对应的,EventThread先启动并挂起,启动后等待需要VSync信号的客户端和它创建EventThread.Connection,并加到EventThread.mDisplayEventConnections中,同时唤醒EventThread,EventThread被唤醒后接收到VSync信号会将该事件通过EventThread.Connection.postEvent将同步信号时间分发到各个客户端Connection连接;
(6)Connection里面包含BitTube对象,该对象有一对直连的socket,一端发送,另一端就可以收到,SF和应用进程都是通过底层的loop(epoll机制)监听BitTube的ReceiveFd,然后把该同步信号分发到需要的地方。

3.2 回答最前面提出的问题

(1)VSync是如何产生的?
答:对于支持HWC的设备而言,HWC设备是在SF进程中打开并维护的,VSync信号由HWC设备产生,每次产生VSync信号会回调到HWComposer::hook_vsync函数。
(2)VSync最初是在哪个进程中捕获的?
答:VSync最初被HWComposer::hook_vsync传递到SF.onVSyncReceived函数中,并且经过SF一层封装成DispSync信号源。

剩下的两个问题等到下面分析SF进程和应用进程请求和获取VSync信号的时候再记录。

Android 中,VSYNC 是通过硬件中断来触发的。具体来说,Android 设备的硬件会以固定的帧率(通常为 60Hz)发送 VSYNC 信号,这个信号会被传递到系统的 VSYNC 时钟中。Android 系统中有一个名为 SurfaceFlinger 的系统服务,它是 Android 图形系统的重要组成部分,主要负责屏幕的渲染和显示。SurfaceFlinger 会注册一个 VSYNC 时钟回调函数,当 VSYNC 信号到来时,VSYNC 时钟回调函数就会被调用。在 SurfaceFlinger 的 VSYNC 时钟回调函数中,会触发 Choreographer 的回调函数,以便使用 Choreographer 协调应用程序的 UI 绘制和动画。 具体来说,在 SurfaceFlinger 的 VSYNC 时钟回调函数中,会执行下面这段代码: ```java // 利用 Choreographer 处理 VSYNC 事件 final long vsyncTime = now; final long intendedVsync = vsyncTime + mFrameIntervalNanos; final long frameStartTime = System.nanoTime(); mChoreographer.doFrame(frameStartTime, intendedVsync); ``` 其中,mChoreographer 是一个 Choreographer 对象,doFrame() 方法是 Choreographer 的一个回调函数,用于处理 VSYNC 事件。在 doFrame() 方法中,会执行下面这些操作: 1. 执行任务队列中的 CALLBACK_TRAVERSAL 类型的任务。 2. 执行任务队列中的 CALLBACK_COMMIT 类型的任务。 3. 执行 Choreographer 自定义的回调函数(例如 FrameCallback)。 通过这种方式Android 系统就能够很好地协调应用程序的 UI 绘制和动画,以保证应用程序的帧率稳定性和流畅性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值