Android GUI系统之SurfaceFlinger(06)服务端分析1-处理VSYNC
发布日期:2021-05-10 22:02:02 浏览次数:11 分类:精选文章

本文共 15692 字,大约阅读时间需要 52 分钟。

该系列文章总纲链接:


本章关键点总结 & 说明:

本章节思维导图如上。主要讲述了SurfaceFlinger 处理Vsync机制的流程。分析到处理消息这一部分。


1 SurfaceFlinger使用VSync流程框架

APP将产生的界面提交Buffer时会调用queueBuffer的操作,最后会通知SF合成界面。SF需要合成界面的时候,发送请求Vsync信号请求给EventThread(SF),EventThread(SF) 再向DispSyncThread线程发送请求,DispSyncThread线程收到请求后,延迟offset2后将VSync-SF发送给EventThread(SF) 并唤醒, EventThread(SF)在收到Vsync-SF后唤醒SF,SF开始合成新界面。整体框架如下所示:

2 SurfaceFlinger使用VSync流程 源码分析

2.1 分析模式

以上面的框架为基础,这里详细分析下该流程。当应用程序构造好数据后 通知SurfacFlinger,这部分在之前的章节中过已经分享过,因此这里代码直接从框架图的 第2步 开始分析。

2.2 SF向EventThread-SF 请求VSync

这里实际上是继续 章节4()的分析,mFlinger->signalLayerUpdate(),代码如下:

void SurfaceFlinger::signalLayerUpdate() {    mEventQueue.invalidate();}

这里就是 唤醒 另外一个线程EventThread-SF,继续分析mEventQueue.invalidate,代码实现如下:

void MessageQueue::invalidate() {#if INVALIDATE_ON_VSYNC    mEvents->requestNextVsync();#else    mHandler->dispatchInvalidate();#endif}

mEvents是EventThread::Connection类型的,对应的代码如下:

void EventThread::Connection::requestNextVsync() {    mEventThread->requestNextVsync(this);}

这里继续分析EventThread的requestNextVsync方法,代码实现如下:

void EventThread::requestNextVsync(        const sp
& connection) { Mutex::Autolock _l(mLock); if (connection->count < 0) { connection->count = 0; mCondition.broadcast(); }}

这里条件变量唤醒了当前的线程EventThread,那么另一个地方的wait被唤醒,这里就是EventThread::waitForEvent方法中的mCondition.wait(mLock),被唤醒后继续执行。

2.3 EventThread-SF向 DispSyncThread请求VSync

首先分析下EventThread线程的启动,即threadLoop的实现,代码如下:

bool EventThread::threadLoop() {    DisplayEventReceiver::Event event;    Vector< sp
> signalConnections; //关键点1:等待事件 signalConnections = waitForEvent(&event); const size_t count = signalConnections.size(); for (size_t i=0 ; i
& conn(signalConnections[i]); // now see if we still need to report this event //关键点2:post事件 status_t err = conn->postEvent(event); if (err == -EAGAIN || err == -EWOULDBLOCK) { //... } else if (err < 0) { //... removeDisplayEventConnection(signalConnections[i]); } } return true;}

这里详细分析下waitForEvent,代码如下:

Vector< sp
> EventThread::waitForEvent( DisplayEventReceiver::Event* event){ Mutex::Autolock _l(mLock); Vector< sp
> signalConnections; do { bool eventPending = false; bool waitForVSync = false; size_t vsyncCount = 0; nsecs_t timestamp = 0; for (int32_t i=0 ; i
connection(mDisplayEventConnections[i].promote()); if (connection != NULL) { bool added = false; if (connection->count >= 0) {//表示需要得到VSync waitForVSync = true; if (timestamp) { if (connection->count == 0) { connection->count = -1; signalConnections.add(connection); added = true; } else if (connection->count == 1 || (vsyncCount % connection->count) == 0) { signalConnections.add(connection); added = true; } } } if (eventPending && !timestamp && !added) { signalConnections.add(connection); } } else { mDisplayEventConnections.removeAt(i); --i; --count; } } // Here we figure out if we need to enable or disable vsyncs if (timestamp && !waitForVSync) { disableVSyncLocked(); } else if (!timestamp && waitForVSync) { //如果需要Vsync,则调用该方法 enableVSyncLocked(); } if (!timestamp && !eventPending) { // wait for something to happen if (waitForVSync) { bool softwareSync = mUseSoftwareVSync; nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000); if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) { mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY; mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); mVSyncEvent[0].vsync.count++; } } else { //休眠,等待下一个VSync到来 mCondition.wait(mLock); } } } while (signalConnections.isEmpty()); return signalConnections;}

这里一旦表明需要VSync,则会调用关键方法enableVSyncLocked,代码实现如下:

void EventThread::enableVSyncLocked() {    if (!mUseSoftwareVSync) {        // never enable h/w VSYNC when screen is off        if (!mVsyncEnabled) {            mVsyncEnabled = true;            //这里的mVSyncSource是DispSyncSource类型的            //实际上是给DispSyncThread线程设置Callback            mVSyncSource->setCallback(static_cast
(this)); mVSyncSource->setVSyncEnabled(true); } } mDebugVsyncEnabled = true; sendVsyncHintOnLocked();}

继续分析,mVSyncSource是DispSyncSource类的对象,因此setCallback的代码实现如下:

virtual void setCallback(const sp
& callback) { Mutex::Autolock lock(mMutex); mCallback = callback; }

这里设置了callback,后面 DispSyncThread就可以在收到VSync信号时调用该callback方法了。

2.4 唤醒DispSyncThread

这里以HWC的VSyncThread(实际上软件硬件 实现最终结果都是一样的),也就是软件实现的VSync来分析,软件VsyncThread的线程代码实现如下:

bool HWComposer::VSyncThread::threadLoop() {    { // scope for lock        Mutex::Autolock _l(mLock);        while (!mEnabled) {            mCondition.wait(mLock);        }    }    const nsecs_t period = mRefreshPeriod;    const nsecs_t now = systemTime(CLOCK_MONOTONIC);    nsecs_t next_vsync = mNextFakeVSync;    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);    if (err == 0) {        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);    }    return true;}

这里经过一段运算后,调用了 mHwc.mEventHandler.onVSyncReceived方法,mHwc.mEventHandler的值实际上就是SurafceFlinger,这在SurafceFlinger的init函数中有做,代码如下:

mHwc = new HWComposer(this,            *static_cast
(this));

因此,这里继续分析SurafceFlinger的onVSyncReceived方法的实现,代码如下:

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);    }}

这里继续分析DispSync的addResyncSample的实现,代码如下:

bool DispSync::addResyncSample(nsecs_t timestamp) {    Mutex::Autolock lock(mMutex);    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;    mResyncSamples[idx] = timestamp;    if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {        mNumResyncSamples++;    } else {        mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;    }    updateModelLocked();    if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {        resetErrorLocked();    }    if (kIgnorePresentFences) {        return mThread->hasAnyEventListeners();    }    return mPeriod == 0 || mError > kErrorThreshold;}

这里继续分析DispSync的updateModelLocked的实现,代码如下:

void DispSync::updateModelLocked() {    if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {        nsecs_t durationSum = 0;        for (size_t i = 1; i < mNumResyncSamples; i++) {            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;            size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;            durationSum += mResyncSamples[idx] - mResyncSamples[prev];        }        mPeriod = durationSum / (mNumResyncSamples - 1);        double sampleAvgX = 0;        double sampleAvgY = 0;        double scale = 2.0 * M_PI / double(mPeriod);        for (size_t i = 0; i < mNumResyncSamples; i++) {            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;            nsecs_t sample = mResyncSamples[idx];            double samplePhase = double(sample % mPeriod) * scale;            sampleAvgX += cos(samplePhase);            sampleAvgY += sin(samplePhase);        }        sampleAvgX /= double(mNumResyncSamples);        sampleAvgY /= double(mNumResyncSamples);        mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);        if (mPhase < 0) {            mPhase += mPeriod;        }        // Artificially inflate the period if requested.        mPeriod += mPeriod * mRefreshSkipCount;        mThread->updateModel(mPeriod, mPhase);    }}

这里继续分析mThread->updateModel的实现,代码如下:

void updateModel(nsecs_t period, nsecs_t phase) {    Mutex::Autolock lock(mMutex);    mPeriod = period;    mPhase = phase;    mCond.signal();}

经过一系列的分析,SurafceFlinger的onVSyncReceived方法最终会唤醒DispSyncThread线程。

2.5 DispSyncThread唤醒EventThread

有mCond.signal()就有对应的mCond.wait(),该方法在线程执行体中threadloop中,threadloop的代码如下:

virtual bool threadLoop() {    status_t err;    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);    nsecs_t nextEventTime = 0;    while (true) {        Vector
callbackInvocations; nsecs_t targetTime = 0; { // Scope for lock Mutex::Autolock lock(mMutex); if (mStop) { return false; } if (mPeriod == 0) { err = mCond.wait(mMutex); //... continue; } /*计算最近的EventThread的时间。 Eventthread发现connection>=0时, 向线程DispSyncThread注册成callback,成为listener */ nextEventTime = computeNextEventTimeLocked(now); targetTime = nextEventTime; bool isWakeup = false; if (now < targetTime) {//休眠 err = mCond.waitRelative(mMutex, targetTime - now); if (err == TIMED_OUT) { isWakeup = true; } else if (err != NO_ERROR) { //... } } now = systemTime(SYSTEM_TIME_MONOTONIC); if (isWakeup) { mWakeupLatency = ((mWakeupLatency * 63) + (now - targetTime)) / 64; if (mWakeupLatency > 500000) { // Don't correct by more than 500 us mWakeupLatency = 500000; } } //手机所有的callback callbackInvocations = gatherCallbackInvocationsLocked(now); } if (callbackInvocations.size() > 0) { //调用callback fireCallbackInvocations(callbackInvocations); } } return false;}

这里fireCallbackInvocations的调用Callback实际上最终调用的就是EventThread-SF的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();}

至此EventThread-SF就被DispSyncThread给唤醒了。

2.6 EventThread-SF唤醒SurfaceFlinger

被DispSyncThread线程唤醒后,会执行对应的mCondition.wait,相关代码在waitforEvent中,相关代码如下:

bool EventThread::threadLoop() {    DisplayEventReceiver::Event event;    Vector< sp
> signalConnections; //关键点1:等待事件 signalConnections = waitForEvent(&event); const size_t count = signalConnections.size(); for (size_t i=0 ; i
& conn(signalConnections[i]); // now see if we still need to report this event //关键点2:post事件 status_t err = conn->postEvent(event); if (err == -EAGAIN || err == -EWOULDBLOCK) { //... } else if (err < 0) { //... removeDisplayEventConnection(signalConnections[i]); } } return true;}

此时waitforEvent结束后,会进入到这个循环,会调用connection的 postEvent方法,继续分析,代码实现如下:

status_t EventThread::Connection::postEvent(        const DisplayEventReceiver::Event& event) {    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);    return size < 0 ? status_t(size) : status_t(NO_ERROR);}

 

前面发送消息后必然会有一个接收端。但接收端直接分析并不容易,我们需要从SF中查找,在SF的init的代码中 ,关注这段代码:

void SurfaceFlinger::init(){    //...    sp
vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc); sp
sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread);//关键点 //...}

专门分析mEventQueue.setEventThread(mSFEventThread)的实现,代码如下:

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

这里主要是监听 EventThread是否有数据,专注分析MessageQueue::cb_eventReceiver的实现,代码如下:

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {    MessageQueue* queue = reinterpret_cast
(data); return queue->eventReceiver(fd, events);}

这里继续分析queue->eventReceiver,代码实现如下:

int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {    ssize_t n;    DisplayEventReceiver::Event buffer[8];    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {        for (int i=0 ; i
dispatchInvalidate();#else mHandler->dispatchRefresh();#endif break; } } } return 1;}

这里DisplayEventReceiver::getEvents 和 之前的sendEvent操作相对应。即SF 执行init后一直监听事件,如果有的话,则调用

mHandler->dispatchInvalidate()方法。

2.7 处理

void MessageQueue::Handler::dispatchInvalidate() {    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));    }}

这里实用了handler Message机制,因此直接看handleMessage的处理,如下:

void MessageQueue::Handler::handleMessage(const Message& message) {    switch (message.what) {        case INVALIDATE:            android_atomic_and(~eventMaskInvalidate, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;        case REFRESH:            android_atomic_and(~eventMaskRefresh, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;        case TRANSACTION:            android_atomic_and(~eventMaskTransaction, &mEventMask);            mQueue.mFlinger->onMessageReceived(message.what);            break;    }}

这里的INVALIDATE对应mQueue.mFlinger->onMessageReceived(message.what)方法的执行,onMessageReceived代码实现如下:

void SurfaceFlinger::onMessageReceived(int32_t what) {    switch (what) {        case MessageQueue::TRANSACTION: {            handleMessageTransaction();            break;        }        case MessageQueue::INVALIDATE: {            //关键语句            bool refreshNeeded = handleMessageTransaction();//1             refreshNeeded |= handleMessageInvalidate();//2             refreshNeeded |= mRepaintEverything;            if (refreshNeeded) {                signalRefresh();//3            }            break;        }        case MessageQueue::REFRESH: {            handleMessageRefresh();            break;        }    }}

针对INVALIDATE消息,关键执行代码中标识的几句话。第7节我们详细分析这一部分。

 

 

上一篇:社群联盟(01)管理模型
下一篇:Android GUI系统之SurfaceFlinger(05)VSync机制

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年04月05日 19时49分44秒