接着上篇文章中的两个新疑问:
- mEventTube是个什么玩意?
- 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<ConnectionHandle, Connection> 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));
}
}
疑问解答
-
mEventTube即BitTube是个什么玩意?
BitTube创建一对相互连接好的socket,其中一个用于发消息,另一个用于接收消息。比如BitTube A初始化了一对socket,可以将发送或者接收fd转移到另一个BitTube B对象,因此BitTube A对象就可以和BitTube B通信了。很明显通信方式为单工。 -
MessageQueue::setEventConnection(…) 什么时候有谁调用的 ?
在Surfacelinger中的initScheduler函数中创建了EventThreadConnection,EventThreadConnection中的mChannel为BitTube,将EventThreadConnection通过函数MessageQueue::setEventConnection(…) 将mChannel的receiveFd转移到MessageQueue::mEventTube中。因此EventThreadConnection::mChannel发消息,MessageQueue::mEventTube接收消息。
SurfaceFlinger消息驱动图
- surfaceflinger主进程初始化完成后,由MessageQueue::waitMessage() 死循环处理消息,循环触发surfaceflinger合成显示等动作。
- Looper中处理两件事情:
<1> surfaceflinger中会主动请求Vsync信号,并通过epoll监听Vsync事件,当Vsync事件到来后转成INVALIDATE消息,并由Handler处理此消息,推动下一次合成。
<2> surfaceflinger中会主动调用refresh(), 即向Looper中send REFRESH消息,并由Handler处理此消息强制刷新画面。