和你一起终身学习,这里是程序员Android
经典好文推荐,通过阅读本文,您将收获以下知识点:
一、Consumer端的FrameListener
二、消息队列MessageQueue
三、显示设备DispalyDevice
通过前面的简单介绍,我们对HWC合成有大致的了解。下面我们根据实际代码进行讲解。前面章节,我们已经说过,Layer的创建,和BufferQueue,那么Buffer进入到BufferQueue队列中后,怎么进行合成显示的呢?我们继续来看。
一、Consumer端的FrameListener
你还记得Producer的frameAvailableListener吗?Buffer放入队列BufferQueue后,是不是通过frameAvailableListener->onFrameAvailable
通知Consumer?大家可以再回望一下BufferQueueProducer::queueBuffer
。
frameAvailableListener是哪里来的?
我们先来看一下Consumer中Listener间的相互关系
image
BufferLayer有专门的Consumer,BufferLayerConsumer;BufferLayerConsumer继承ConsumerBase。ConsumerBase通过IGraphicBufferConsumer和BufferQueue进行通信的。
BufferQueue中的frameAvailableListener,是一个IConsumerListener的接口,对应的Binder的Bn端实现为ProxyConsumerListener。
BufferLayer实现了ContentsChangedListener,ContentsChangedListener继承FrameAvailableListener。BufferLayer的Listener实现,被传给了ConsumerBase。
ConsumerBase实现ConsumerListener接口,构建ConsumerBase时,会创建ProxyConsumerListener,将ConsumerBase实现的Listener接口传给ProxyConsumerListener。
BufferQueue中Listener回调时,会回调到ConsumerBase中。ConsumerBase中再通过BufferLayer实现的,传下来的Listener回调到BufferLayer中。
层层回调,别弄混淆了。
关键代码:
BufferQueueProducer中通过frameAvailableListener->onFrameAvailable
回调到ProxyConsumerListener中:
* frameworks/native/libs/gui/BufferQueue.cpp
void BufferQueue::ProxyConsumerListener::onFrameAvailable(
const BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
if (listener != NULL) {
listener->onFrameAvailable(item);
}
}
ProxyConsumerListener中的mConsumerListener是ConsumerBase中的实现。这里的listener->onFrameAvailable
将回调到ConsumerBase中。
* frameworks/native/libs/gui/ConsumerBase.cpp
void ConsumerBase::onFrameAvailable(const BufferItem& item) {
CB_LOGV("onFrameAvailable");
sp<FrameAvailableListener> listener;
{ // scope for the lock
Mutex::Autolock lock(mFrameAvailableMutex);
listener = mFrameAvailableListener.promote();
}
if (listener != NULL) {
CB_LOGV("actually calling onFrameAvailable");
listener->onFrameAvailable(item);
}
}
ConsumerBase中的mFrameAvailableListener是BufferLayer中的实现:
* frameworks/native/services/surfaceflinger/BufferLayer.cpp
void BufferLayer::onFrameAvailable(const BufferItem& item) {
// Add this buffer from our internal queue tracker
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
item.mGraphicBuffer->getHeight(),
item.mFrameNumber);
// Reset the frame number tracker when we receive the first buffer after
// a frame number reset
if (item.mFrameNumber == 1) {
mLastFrameNumberReceived = 0;
}
// Ensure that callbacks are handled in order
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
ms2ns(500));
if (result != NO_ERROR) {
ALOGE("[%s] Timed out waiting on callback", mName.string());
}
}
mQueueItems.push_back(item);
android_atomic_inc(&mQueuedFrames);
// Wake up any pending callbacks
mLastFrameNumberReceived = item.mFrameNumber;
mQueueItemCondition.broadcast();
}
mFlinger->signalLayerUpdate();
}
BufferLayer中调用onFrameAvailable,去通知SurfaceFlinger进行合成。
到这里,应用端(Producer)生产完Buffer这件事,就通知到了SurfaceFlinger中了。
SurfaceFlinger的signalLayerUpdate,是通过MessageQueue来处理的,我们先来看看MessageQueue。
二、消息队列MessageQueue
MessageQueue是SurfaceFlinger中的消息队列,为什么需要消息队列?我们应用有一个主线程,专门进行UI的处理。SurfaceFlinger同样的,也有一个主线程,SurfaceFlinger的主线程主要进行显示数据的处理,也就是合成。
SurfaceFlinger中,mEventQueue是MessageQueue的一个栈对象,采用mutable修饰。SurfaceFlinger在初次引用时,会对mEventQueue进行初始化。
* frameworks/native/services/surfaceflinger/MessageQueue.cpp
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
MessageQueue初始化时,创建了一个Looper和一个Handler。
此外,在SurfaceFlinger初始化时,创建了一个EventThread,并传给了MessageQueue。
void SurfaceFlinger::init() {
... ...
sp<VSyncSource> sfVsyncSrc =
new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
MessageQueue的setEventThread函数如下:
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
if (mEventThread == eventThread) {
return;
}
if (mEventTube.getFd() >= 0) {
mLooper->removeFd(mEventTube.getFd());
}
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
}
MessageQueue在setEventThread时,主要做以下几件事:
创建一个BitTube对象mEventTube
创建一个EventConnection
sp<EventThread::Connection> EventThread::createEventConnection() const {
return new Connection(const_cast<EventThread*>(this));
}
Connection在第一次引用时,将会被注册到mEventThread中。
void EventThread::Connection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}
在注册时,Connection将会被添加到mDisplayEventConnections 中。
status_t EventThread::registerDisplayEventConnection(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
mDisplayEventConnections.add(connection);
mCondition.broadcast();
return NO_ERROR;
}
mDisplayEventConnections是一个已经注册的Connection的集合。
将mEventTube和EventConnection关联
status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
outChannel->setReceiveFd(mChannel.moveReceiveFd());
return NO_ERROR;
}
Connection创建时,将默认创建一个4k的BitTube,BitTube封装的是一对socket,一个发送,一个接收,可传输的Buffer大小为4K。
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(err