AndroidQ 图形系统(8)SurfaceFlinger合成之Vsync处理

AndroidQ 图形系统(4)queueBuffer函数分析我们知道一块buffer被queue到buffer队列之后就会回调onFrameAvailable函数通知SurfaceFlinger进行消费:

if (frameAvailableListener != nullptr) {
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != nullptr) {
            frameReplacedListener->onFrameReplaced(item);
        }

我们先来看看onFrameAvailable调用流程:

  1. 这里的frameAvailableListenerBufferQueueCoremConsumerListener
  2. BufferQueueCoremConsumerListenerConsumerBase构造函数传过来的BufferQueue::ProxyConsumerListener
  3. BufferQueue::ProxyConsumerListener中的listener又是ConsumerBase
  4. ConsumerBase中又有一个mFrameAvailableListener,这又是通过外部调用ConsumerBasesetFrameAvailableListener函数传递过来的BufferQueueLayer

所以最终onFrameAvailable函数就是调到BufferQueueLayer中,这是Layer的子类,是SurfaceFlinger进程对Surface的描述。

直接到BufferQueueLayer中来看

BufferQueueLayer::onFrameAvailable

void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
    ATRACE_CALL();
    // Add this buffer from our internal queue tracker
    { // Autolock scope
        ......

        Mutex::Autolock lock(mQueueItemLock);
 		.....

        mQueueItems.push_back(item);
        mQueuedFrames++;

		......
    if (isRemovedFromCurrentState()) {
        ....
    } else {
        .....
        mFlinger->signalLayerUpdate();
    }
    mConsumer->onBufferAvailable(item);
}

这个函数其他内容暂时不管,我们主要来看mFlinger->signalLayerUpdate(),这个函数是请求更新Layer的核心。

SurfaceFlinger::signalLayerUpdate

void SurfaceFlinger::signalLayerUpdate() {
    mScheduler->resetIdleTimer();
    mEventQueue->invalidate();
}

mEventQueue是一个MessageQueue对象,在SurfaceFlinger初始化的时候创建的,和java层的MessageQueue对应的,是属于native层消息机制,它在初始化时同样会有LooperHandler

void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

来看它的invalidate函数,记得java层View中也有一个invalidate方法吗,作用是什么?是用来触发View的绘制的,如何触发?其实就是向底层请求Vsync,等到下一个Vsync到了之后就开始绘制,同样这里的invalidate函数也是类似的功能,也会请求Vsync,收到Vsync之后开始合成,这里的VsyncSurfaceFlinger进程的,顺便提一句,一个Vsync会被分成两部分,一个用于APP绘制,一个用于SurfaceFlinger合成,对应就有两个处理Vsync的线程EventThread,如下就是创建的两个EventThread,一个名为"app",一个名为"sf"。

void SurfaceFlinger::init() {
	......
    mAppConnectionHandle =
            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         resyncCallback,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle =
            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         resyncCallback, [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });

我们继续看MessageQueueinvalidate函数

MessageQueue::invalidate

void MessageQueue::invalidate() {
    mEvents->requestNextVsync();
}

这个mEvents是什么呢?它是一个EventThreadConnection对象,EventThreadConnection是一个很重要的对象,是在SurfaceFlinger的init中创建的:

void SurfaceFlinger::init() {
    ......
    mAppConnectionHandle =
            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         resyncCallback,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle =
            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         resyncCallback, [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });
         }

调用mScheduler->createConnection创建,

Scheduler::createConnection

sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
        const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync,
        ResyncCallback resyncCallback,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    const int64_t id = sNextId++;
    ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);

    std::unique_ptr<EventThread> eventThread =
            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                            offsetThresholdForNextVsync, std::move(interceptCallback));

    auto eventThreadConnection =
            createConnectionInternal(eventThread.get(), std::move(resyncCallback),
                                     ISurfaceComposer::eConfigChangedSuppress);
    mConnections.emplace(id,
                         std::make_unique<Connection>(new ConnectionHandle(id),
                                                      eventThreadConnection,
                                                      std::move(eventThread)));
    return mConnections[id]->handle;
}

这个函数里面分别创建了APP和SF的EventThread,以及APP和SF的EventThreadConnection,用一个ConnectionHandle来封装EventThreadEventThreadConnection,通过id进行标识,将它们保存在mConnections中。
其实创建EventThreadEventThreadConnection都做了非常多的事情,在前面分析Vsync的分发和接收时都分析过,这里我们总结一下,首先说EventThread的初始化:

EventThread

  1. EventThread创建时接收了一个VSyncSource对象,这也是个很重要的对象,主要负责接收硬件的VSync并分发到APP或者SF,使用的是它的子类DispSyncSourceVSyncSource中有一个callback,这个callback的具体实现类是EventThread,并且这个callback会被设置到DispSyncSource中去,也就是说某些情况发生之后(收到Vsync),会在DispSyncSource中调用EventThreadonVSyncEvent函数。
class VSyncSource {
public:
    class Callback {
    public:
        virtual ~Callback() {}
        virtual void onVSyncEvent(nsecs_t when) = 0;
    };
	....
};
  1. 再来看DispSyncSource,它创建时又接收了一个DispSync对象,这个对象才是真正做Vsync的分发和接收的,依靠的是它内部的一个线程DispSyncThread,并且DispSync内部也有一个callback,这个callback是被DispSyncSource实现的,那这个callback会往哪里传呢?
class DispSync {
public:
    class Callback {
    public:
        Callback() = default;
        virtual ~Callback();
        virtual void onDispSyncEvent(nsecs_t when) = 0;
    ......
   };

其实它的传递是从EventThread的内部线程开始的,EventThread内部有两个变量mState和nextState,表示请求Vsync的当前状态和下一次状态,如果两次状态不等并且下一次的状态为State::VSync(代表请求VSync),则调用DispSyncSourcesetVSyncEnabled(true)函数,这个函数会将callback传递到DispSync中去,前面不是说了真正做Vsync接收分发的是DispSync吗,所以当DispSync接收到Vsync就会回调DispSyncSourceonDispSyncEvent函数,onDispSyncEvent中又会回调EventThreadonVSyncEvent函数,然后再看当前EventThread是属于APP还是SF来决定此Vsync到底是发给谁。

if (mState != nextState) {
            if (mState == State::VSync) {
                mVSyncSource->setVSyncEnabled(false);
            } else if (nextState == State::VSync) {
                mVSyncSource->setVSyncEnabled(true);
            }

            mState = nextState;
        }

Vsync是由DispSync进行管理,DispSync接收来自硬件的Vsync然后一分为二,VSYNC的最终处理者是应用层的Choreographer(绘制),SF_VSYNC的处理者是SurfaceFlinger(合成)。

EventThreadConnection

EventThread的总结就说完了,接着来看看EventThreadConnection,这个类创建过程中最重要的事情就是创建了BitTube

EventThreadConnection::EventThreadConnection(EventThread* eventThread,
                                             ResyncCallback resyncCallback,
                                             ISurfaceComposer::ConfigChanged configChanged)
      : resyncCallback(std::move(resyncCallback)),
        configChanged(configChanged),
        mEventThread(eventThread),
        mChannel(gui::BitTube::DefaultSize) {}

BitTube初始化时又创建了一对非常重要的socket

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // since we don't use the "return channel", we keep it small...
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
        mReceiveFd.reset(sockets[0]);
        mSendFd.reset(sockets[1]);
    } else {
        mReceiveFd.reset();
        ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
    }
}

这对socket可以用于全双工通信,每一个socket既可以读也可以写。例如,可以往socket[0]中写,从socket[1]中读,或者从socket[1]中写,从socket[0]中读。
读、写操作可以位于同一个进程,也可以分别位于不同的进程。

通过socketpair创建好了一对socket之后,再通过setsockoptsocket进行设置,再调用fcntl函数针对socket描述符提供控制,

最后mReceiveFd.reset(sockets[0]),mSendFd.reset(sockets[1])建立Fd与socket的关联,很明显这一对socket一个用来接收消息,一个用来发送消息,那到底是接收和发送什么消息,其实就是Vsync,当Vsync到来的时候通过mSendFd写入消息,然后APP或者SF监听mReceiveFd接受消息,就完成了对Vsync的接收,而完成监听mReceiveFd,就能够收到mSendFd的发送的消息依靠的是Handler消息机制,Handler处理消息的顺序是先处理native层message,再处理request,最后处理java层消息,这个request其实监听的各种fd。

当我们需要监听一对fd时,首先需要调用Looper的addFd函数将fd添加到Handler监听,addFd这个函数会将fd的以及一系列和此fd有关的信息封装为request,然后加入监听,其中比较重要的除了fd还有一个就是callback,即收到此fd对端的消息之后要回调的函数。

for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
          if (response.request.ident == POLL_CALLBACK) {
              int fd = response.request.fd;
              int events = response.events;
              void* data = response.request.data;
 
              int callbackResult = response.request.callback->handleEvent(fd, events, data);
              if (callbackResult == 0) {
                  removeFd(fd, response.request.seq);
              }
  
              response.request.callback.clear();
              result = POLL_CALLBACK;
          }
      }

上面这一段代码就是Handler收到消息之后会找到对应处理此消息的request,然后调用通过addFd传递过来的callback的handleEvent回调函数。

我们继续来看SurfaceFlinger进程注册监听Vsync的fd的过程

SurfaceFlinger::init

void SurfaceFlinger::init() {
	......	
	mSfConnectionHandle =
            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         resyncCallback, [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });
    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
	......
}

注意这里只注册了SurfaceFlinger进程监听Vsync的fd,APP进程是在其他地方注册的,AndroidQ 应用层Vsync信号的注册与接收(上)这篇文章分析过了。

MessageQueue::setEventConnection

void MessageQueue::setEventConnection(const sp<EventThreadConnection>& connection) {
    if (mEventTube.getFd() >= 0) {
        mLooper->removeFd(mEventTube.getFd());
    }
    mEvents = connection;
    mEvents->stealReceiveChannel(&mEventTube);
    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                   this);
}

看到了吗,这里调用了mLooper->addFd,第一个参数就是BitTube中的mReceiveFd,再看第四个参数,这就是callback,等会儿回来看。

Looper::addFd

int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
      return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : nullptr, data);
  }

我们发现LooperaddFd中接收的callback是一个Looper_callbackFunc类型:

typedef int (*Looper_callbackFunc)(int fd, int events, void* data);

其实就是个int型函数指针,接着我们从MessageQueue传过来的callback会被封装成一个SimpleLooperCallback,它继承LooperCallback,并且callback赋值给了SimpleLooperCallbackmCallback,它的handleEvent函数直接调用的我们传递过来的这个callback,所以我们会发现Handler收到消息是回调的handleEvent函数,而MessageQueue中确找不到这个函数的实现,其实中间有了这一层转换。

SimpleLooperCallback::SimpleLooperCallback(Looper_callbackFunc callback) :
          mCallback(callback) {
  }

  SimpleLooperCallback::~SimpleLooperCallback() {
  }
  
  int SimpleLooperCallback::handleEvent(int fd, int events, void* data) {
      return mCallback(fd, events, data);
  }

好了我们再来看看MessageQueue中这个callback的实现:

MessageQueue::cb_eventReceiver

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

记得addFd最后一个参数传了个this吗,这里this又被传回来了,接着调用MessageQueueeventReceiver函数:

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 < n; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                mFlinger->mVsyncTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
                mHandler->dispatchInvalidate();
                break;
            }
        }
    }
    return 1;
}

这里while循环中先调用DisplayEventReceivergetEvents函数其实最终调到了BitTube中,其目的就是去读mSendFd写的数据,这里只处理类型为DISPLAY_EVENT_VSYNC也就是Vsync的事件,一共有这么几个类型:

 enum {
 	 DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'), 
 	 DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'), 
     DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'),
  };

然后调用mHandler->dispatchInvalidate函数进一步处理,

dispatchInvalidate

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

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

其实就是发送一个INVALIDATE消息,然后自己的handleMessage进行处理。

到此我们已经了解了Vsync是怎么接收的以及接收之后干什么,我们先不继续往下分析,回到最开始去看看Vsync是怎么发送出来的,来看开始的onFrameAvailable中调用的SurfaceFlinger::signalLayerUpdate

void SurfaceFlinger::signalLayerUpdate() {
    mScheduler->resetIdleTimer();
    mEventQueue->invalidate();
}

MessageQueue::invalidate

void MessageQueue::invalidate() {
    mEvents->requestNextVsync();
}

看到了吗,这代码多明显,请求Vsync,Vsync是请求一次才能接收一次,所以当APP每绘制完一帧交给SurfaceFlingerSurfaceFlinger都会请求Vsync然后进行合成,其实SF的requestNextVsync和APP的执行流程差不多,只是EventThreadEventThreadConnection分属不同,这里调用EventThreadConnectionrequestNextVsync函数直接调用的EventThread的同名函数:

void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    if (connection->resyncCallback) {
        connection->resyncCallback();
    }

    std::lock_guard<std::mutex> lock(mMutex);

    if (connection->vsyncRequest == VSyncRequest::None) {
        connection->vsyncRequest = VSyncRequest::Single;
        mCondition.notify_all();
    }
}

VSyncRequest定义在EventThread.h中:

enum class VSyncRequest {
    None = -1,
    Single = 0,
    Periodic = 1,
    // Subsequent values are periods.
};

代表了当前VSync请求的三种状态,None为初始值,Single代表已经请求了一个VSync,是一次性的,Periodic代表请求的是周期性信号。

我们收到VSync是需要自己请求的,请求一次,接收一次,而底层的VSync是以周期性在发送的,通常情况为16.6ms一次.

看到这里就能够知道为什么APP和SF请求的Vsync是一次性的了
VSyncRequest为none时,给它赋值为Single,同一时间多次请求无效,接着调用 mCondition.notify_all()函数,mCondition定义在EventThread.h中,类型为std::condition_variable,这是一个条件变量,它在这里最大的用处就是唤醒/等待,那它唤醒的是什么呢?

唤醒的是EventThread内部线程,EventThread内部线程是一个死循环,主要用于处理Vsync接收和分发,接收来自DispSyncVsync,分发给APP或者SF,这个线程我前面这篇文章有详细分析过
AndroidQ SurfaceFlinger进程对Vsync的接收与分发(上)

我这里贴一下对此函数分析的总结:

  1. threadMain首先会开启一个死循环,这个循环会一直处理事件。
  2. mPendingEvents 头部获取 VSYNC 事件 Event
  3. 遍历 mDisplayEventConnections ,找到其中所有 vsyncRequest 不为None的 connection ,并将这些 connection 放入 consumers
  4. 调用 dispatchEvent(*event, consumers) 分发事件,事件会分发给 consumers 中的所有 connection
  5. 根据 mState nextState 的对比,选择 setVSyncEnabled(false) 还是 (true) ,当从State::VSync变为其他状态时调用setVSyncEnabled(false),当从其他状态变为State::VSync时调用setVSyncEnabled(true),mState和nextState的对比其实是起到一个开关作用。
  6. 如果没有事件并且线程状态为State::Idle,则通过条件变量mCondition让线程陷入等待,如果没有事件并且线程状态不为State::Idle时则需要伪造VSync发送给请求者。

这里面最重要的

  1. 是调用setVSyncEnabled(true)函数,这个函数会将DispSync::Callback传递到DispSync中去,传过去干什么?去接收Vsync,然后回调onDispSyncEvent函数。onDispSyncEvent又会回调EventThread实现的callback onVSyncEvent函数,从而将Vsync一步一步送到了EventThread中。
  2. onVSyncEvent收到Vsync之后会调用dispatchEvent函数分发Vsync,分发的实质就是向mSendFd写入消息,这样我们监听的mReceiveFd就收到了。

DispSyncVsync又是来自哪里呢?调用栈如下:
BHwBinder->BnHwComposerCallback::onTransact
->BnHwComposerCallback::_hidl_onVsync
->ComposerCallbackBridge::onVsync
->SurfaceFlinger::onVsyncReceived

到了SurfaceFlinger::onVsyncReceived之后再传给DispSync的。

这很明显就是HAL层回调过来的,具体就不详细看了,到此我们已经知道了当APP绘制好一帧之后queueBufferQueue中,并调用onFrameAvailable函数通知SurfaceFlinger去取,之后就是调用SurfaceFlingersignalLayerUpdate函数,此函数的目的就是请求SurfaceFlinger进程的Vsync,在收到Vsync之后在MessageQueue中通过Handler发送INVALIDATE的消息,接下来就是处理INVALIDATE了,本篇文章暂时就不继续分析了,后面再详细看处理INVALIDATE的过程。

你可能感兴趣的:(Android图形系统)