【surfaceflinger源码分析】surfaceflinger进程的消息驱动模型(二)

接着上篇文章中的两个新疑问:

  1. mEventTube是个什么玩意?
  2. MessageQueue::setEventConnection(…) 什么时候有谁调用的 ?

BitTube

mEventTube的类型为class BitTube,BitTube从字面上的意思来看bit管道,bit隧道,应该是一种传递消息的通道。很显然mEventTube的接收信息的一方是surfaceflinger中的class MessageQueue,那么它的发送方是谁呢 ?
先来看看class BitTube的定义

class BitTube : public Parcelable {
public:
    BitTube() = default;
    explicit BitTube(size_t bufsize);
    struct DefaultSizeType {};
    static constexpr DefaultSizeType DefaultSize{};
    explicit BitTube(DefaultSizeType);
    explicit BitTube(const Parcel& data);
    virtual ~BitTube() = default;

    status_t initCheck() const;
    int getFd() const;
    int getSendFd() const;
    base::unique_fd moveReceiveFd();
    void setReceiveFd(base::unique_fd&& receiveFd);
    void setSendFd(base::unique_fd&& sendFd);
    .........................;
private:
    void init(size_t rcvbuf, size_t sndbuf);
    ssize_t write(void const* vaddr, size_t size);
    ssize_t read(void* vaddr, size_t size);
    mutable base::unique_fd mSendFd;
    mutable base::unique_fd mReceiveFd;
    static ssize_t sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize);
    static ssize_t recvObjects(BitTube* tube, void* events, size_t count, size_t objSize);
};

从上面的定义来看,有个mSendFd和mReceiveFd,并且是通过接口设置进来的。在setEventConnection中的stealReceiveChannel有调用setReceiveFd和setSendFd。先看看setEventConnection是咋回事。

setEventConnection

void MessageQueue::setEventConnection(const sp<EventThreadConnection>& connection) {
    if (mEventTube.getFd() >= 0) {
        //如果recieve fd存在,则将此fd从epoll中删除
        // epoll_ctl(mEpollFd.get(), EPOLL_CTL_DEL, fd, nullptr)
        mLooper->removeFd(mEventTube.getFd());
    }
    mEvents = connection;
    //看样子是要从connection将recieve fd偷过来
    mEvents->stealReceiveChannel(&mEventTube);
    //将偷过来的fd 添加到epoll中
    //epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem)
    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                   this);
}

继续看看EventThreadConnection::stealReceiveChannel(…)

status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
    //将EventThreadConnection中名为mChannel的BitTube的receiveFd转移并设置到MessageQueue中的mEventTube
    outChannel->setReceiveFd(mChannel.moveReceiveFd());
    //将EventThreadConnection中名为mChannel的BitTube的sendFd复制一份并设置到MessageQueue中的mEventTube
    outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
    //设置完成之后,mChannel只能send消息,mEventTube既可以send又可以receive消息。
    return NO_ERROR;
}

有个疑问,mChannel的receiveFd和sendFd是哪里来的呢 ?
surfaceflinger的initScheduler函数中有调用setEventConnection,看看这个被设置进来的connection如何初始化receiveFd和sendFd

void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) {
    ........................;
    mScheduler =
            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
                                         *mRefreshRateConfigs, *this);
    mAppConnectionHandle =
            mScheduler->createConnection("app", mPhaseConfiguration->getCurrentOffsets().late.app,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle =
            mScheduler->createConnection("sf", mPhaseConfiguration->getCurrentOffsets().late.sf,
                                         [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });
    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
    ........................;
}

sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
    RETURN_IF_INVALID_HANDLE(handle, nullptr);
    return mConnections[handle].connection;
}
//接下来看看mSfConnectionHandle 是如何创建出来的 ?
Scheduler::ConnectionHandle Scheduler::createConnection(
        const char* connectionName, nsecs_t phaseOffsetNs,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    auto vsyncSource = makePrimaryDispSyncSource(connectionName, phaseOffsetNs);
    //创建一个eventThread
    auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource),
                                                           std::move(interceptCallback));
    return createConnection(std::move(eventThread));
}

Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
    const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
    //创建connection
    auto connection =
            createConnectionInternal(eventThread.get(), ISurfaceComposer::eConfigChangedSuppress);
    //将connect插入到mConnections, 索引为handle
    //  std::unordered_map mConnections
    mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
    return handle;
}

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) {
    return eventThread->createEventConnection([&] { resync(); }, configChanged);
}

sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
                                     configChanged);
}

EventThreadConnection::EventThreadConnection(EventThread* eventThread,
                                             ResyncCallback resyncCallback,
                                             ISurfaceComposer::ConfigChanged configChanged)
      : resyncCallback(std::move(resyncCallback)),
        mConfigChanged(configChanged),
        mEventThread(eventThread),
        mChannel(gui::BitTube::DefaultSize) {}
//上面mChannel(gui::BitTube::DefaultSize)会调用下面的构造函数, init函数中会创建fd
//而MessageQueue中的mEventTube使用默认构造函数,不会创建fd
BitTube::BitTube(size_t bufsize) {
    init(bufsize, bufsize);
}

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

疑问解答

  1. mEventTube即BitTube是个什么玩意?
    BitTube创建一对相互连接好的socket,其中一个用于发消息,另一个用于接收消息。比如BitTube A初始化了一对socket,可以将发送或者接收fd转移到另一个BitTube B对象,因此BitTube A对象就可以和BitTube B通信了。很明显通信方式为单工。

  2. MessageQueue::setEventConnection(…) 什么时候有谁调用的 ?
    在Surfacelinger中的initScheduler函数中创建了EventThreadConnection,EventThreadConnection中的mChannel为BitTube,将EventThreadConnection通过函数MessageQueue::setEventConnection(…) 将mChannel的receiveFd转移到MessageQueue::mEventTube中。因此EventThreadConnection::mChannel发消息,MessageQueue::mEventTube接收消息。

SurfaceFlinger消息驱动图

【surfaceflinger源码分析】surfaceflinger进程的消息驱动模型(二)_第1张图片

  1. surfaceflinger主进程初始化完成后,由MessageQueue::waitMessage() 死循环处理消息,循环触发surfaceflinger合成显示等动作。
  2. Looper中处理两件事情:
    <1> surfaceflinger中会主动请求Vsync信号,并通过epoll监听Vsync事件,当Vsync事件到来后转成INVALIDATE消息,并由Handler处理此消息,推动下一次合成。
    <2> surfaceflinger中会主动调用refresh(), 即向Looper中send REFRESH消息,并由Handler处理此消息强制刷新画面。

你可能感兴趣的:(图形/窗口,c++,surfaceflinger,Looper,MessageQueue)