相关文件:
frameworks\native\include\gui\BufferQueue.h
frameworks\native\include\gui\BufferQueueCore.h
frameworks\native\include\ui\BufferQueueDefs.h
顾名思义,BufferQueue是用来保存buffer的queue。Android显示系统中为此提供了两个类BufferQueue和BufferQueueCore,从名字上看两个类都是buffer queue相关,但后者似乎是更核心一些,下面来具体分析这两个类之间的关系。
BufferQueue
BufferQueue类一开始就定义了几个非常重要的关键属性值。
- NUM_BUFFER_SLOTS:BufferQueue类定义了一个queue中能够保存的buffer的最大数量NUM_BUFFER_SLOTS,其数量为64,这是android::BufferQueueDefs命令空间中定义的一个静态常量NUM_BUFFER_SLOTS,因此无法在runtime过程中改变此值。
- INVALID_BUFFER_SLOT:BufferSlot的默认状态,即此BufferSlot还未指向已经存在并且有效的buffer时的状态
- NO_BUFFER_AVAILABLE:一般dequeueBuffer前要查询BufferQueue中是否有buffer可用,如果没有,则返回NO_BUFFER_AVAILABLE,表示当前BufferQueue中没有pending状态的buffer可用。
- PRESENT_LATER:dequeueBuffer时,如果此时buffer还没有准备好,则返回PRESENT_LATER,表示此时dequeueBuffer太早了,等会再来dequeue。
- MAX_MAX_ACQUIRED_BUFFERS:当处于异步模式时,系统要预留2个slot以保证producer和consumer之间的异步关系,因此该值等于NUM_BUFFER_SLOTS-2。
BufferQueue类中还定义了一个ProxyConsumerListener类,其继承关系如下图所示:
从继承关系上看,ProxyConsumerListener类是一个Bn端(服务端)的监听类(从类名上看,似乎使用代理模式,这点待进一步研究)。ProxyConsumerListener类是ConsumerListener类的实现,主要用来保存一个指向真正的consumer object的weak引用。ProxyConsumerListener的主要目的是避免BufferQueue对象和consumer对象的循环引用。
class ProxyConsumerListener : public BnConsumerListener { public: explicit ProxyConsumerListener(const wp& consumerListener); ~ProxyConsumerListener() override; void onDisconnect() override; void onFrameAvailable(const BufferItem& item) override; void onFrameReplaced(const BufferItem& item) override; void onBuffersReleased() override; void onSidebandStreamChanged() override; void addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) override; private: // mConsumerListener is a weak reference to the IConsumerListener. This is // the raison d'etre of ProxyConsumerListener. wp mConsumerListener; };
ProxyConsumerListener的使用在ConsumerBase类。
ProxyConsumerListener的实现比较简单,几个函数的功能如下表所示,显然主要是监听一些动作,当这些对应的事件发生后,及时通知另一端。这里显然做数据同步的功能,具体同步的肯定是producer和consumer两端的关系,这一部分内容待补充。
成员函数 |
功能描述 |
onDisconnect |
通知远端已经断开链接了 |
onFrameAvailable |
通知远端frame已经准备好了 |
onFrameReplaced |
通知远端frame被替换了 |
onBuffersReleased |
通知远端buffer已经release了 |
onSidebandStreamChanged |
|
addAndGetFrameTimestamps |
|
看完ProxyConsumerListener类,BufferQueu就剩下最后一个成员了,也是最重要的一个成员:createBufferQueue函数。
static void createBufferQueue(sp* outProducer, sp * outConsumer, bool consumerIsSurfaceFlinger = false);
显然,这个函数是用来创建buffer queue的,其入参即buffer queue的producer和consumer,最后一个参数指明consumer是否为SurfaceFlinger。该函数的使用有两个地方,一个一个在BufferLayer::onFirstRef函数中,一个在SurfaceFlinger:: processDisplayChangesLocked函数中,这里暂时只讲BufferLayer::onFirstRef里面的使用。该函数似乎是给外接屏使用的,这里暂时不深入。
void BufferLayer::onFirstRef() { // Creates a custom BufferQueue for SurfaceFlingerConsumer to use spproducer; sp consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); if (mFlinger->isLayerTripleBufferingDisabled()) { mProducer->setMaxDequeuedBufferCount(2); } const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); updateTransformHint(hw); }
BufferLayer::onFirstRef是在上层应用请求SurfaceFlinger创建Layer时调用的,即应用告诉SurfaceFlinger它要创建一个Layer(即APP端的窗口、Native层的Surface),此时SurfaceFlinger就会创建创建对应Layer,并为此Layer创建一个对应的BufferQueue,即应用的一个窗口对应一个BufferQueue。那么显然,这里的producer是指应用端对应的窗口,consumer即指SurfaceFlinger(第三个参数指定的)。BufferLayer::onFirstRef函数这里不深入研究。
继续看createBufferQueue函数的源代码,删除次要的代码,其主要代码部分如下:
void BufferQueue::createBufferQueue(sp* outProducer, sp * outConsumer, bool consumerIsSurfaceFlinger) { …… sp core(new BufferQueueCore()); sp producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger)); sp consumer(new BufferQueueConsumer(core)); *outProducer = producer; *outConsumer = consumer; }
首先,他调用BufferQueueCore的构建函数创建了一个core对象,显然这是在说,BufferQueueCore才是buffer queue的核心,真正干活的其实是BufferQueueCore这个类,BufferQueue只是个外壳而已。其次分别创建了producer和consumer对象,返回给了对应的Layer,然后BufferLayer将这两个添加了其内部的Consuerm Listener监听器中,这样创建出来的layer就可以与SurfaceFlinger之间进行相关的数据互动操作了,这里不在深入具体细节,后续专门介绍。
BufferQueueCore
从前面的分析可以看到,BufferQueue类其实只做了一件事情:创建BufferQueueCore。其他什么事情都没做。那么这个BufferQueueCore肯定是非常重要的了。接下来看BufferQueueCore这个类。
BufferQueueCore没有复杂的继承关系,直接继承了RefBase类。
BufferQueueCore定义了当前queue的状态:
- CURRENTLY_CONNECTED_API:值为-1,表示当前有producer连接到buffer queue
- NO_CONNECTED_API:值为0,表示当前没有producer连接到buffer queue
BufferQueueCore
成员变量 |
描述 |
mMutex |
被mutable修饰,表明此锁的状态是随时变化的 |
mIsAbandoned |
该变量表示buffer queue已经不在继续消费push到其中的image buffer数据,初始化时默认为false,当consumerDisconnect时,被设置成true。 |
mConsumerControlledByApp |
表示已经连接的consumer是否被application所控制 |
mConsumerName |
该buffer queue对应的consumer的名字,用于在log中标识buffer queue的所有者 |
mConsumerListener |
用于向已连接的consumer发送通知消息。默认初始化时为NULL,当consumerConnect或consumerDisconnect时写入有效值。 |
mConsumerUsageBits |
包含了consumer想要的flags信息 |
mConsumerIsProtected |
表示conumser是否准备处理受保护的buffer |
mConnectedApi |
表示当前连接到buffer queue的producer API,默认为NO_CONNECTED_API,当connect或disconnect时会发生变化 |
mConnectedPid |
最后一个成功连接到该buffer queue的进程的pid |
mConnectedProducerListener |
该监听器用于处理onBufferRelease通知消息 |
mSlots |
即BufferSlot数组,最大保存NUM_BUFFER_SLOTS个BufferSlot。 mSlots必须与producer侧成镜像状态,这使buffer的所有权在producer和consumer之间进行转换时,可以不用通过Binder来发送GraphicBuffer就能实现。整个数组在初始化时被设置为NULL,当requestBuffer时,才会为slot分配buffer。 |
mFreeSlots |
set |
mFreeBuffers |
list |
mUnusedSlots |
list |
mActiveBuffers |
set |
mQueue |
Vector |
mDequeueCondition |
在同时模式中,供dequeueBuffer方法使用的一个条件变量 |
mDequeueBufferCannotBlock |
表示dequeueBuffer操作是否可以被block。这个标志在producer和consumer被Application所控制的情况下,做connect操作时设置。 |
mDefaultBufferFormat |
buffer format的默认格式,如果dequeueBuffer时没有指定buffer format,则使用此变量所设置的format |
mDefaultWidth |
所分配的buffer的默认宽度,在dequeueBuffer中使用,默认为0 |
mDefaultHeight |
所分配的buffer的默认高度,在dequeueBuffer中使用,默认为0 |
mDefaultBufferDataSpace |
queueBuffer时,如果指定DATA_DATASPACE_UNKNOWN了,则使用此值 |
mMaxBufferCount |
指定一次最大分配的buffer数量,可以由consumer进行设置 |
mMaxAcquiredBufferCount |
指定consumer端一次最大acquire的buffer数量,默认为1.consumer端可以通过调用setMaxAcquiredBufferCount来改变此值,但也仅限在尚有producer连接到buffer queue时生效,This value is used to derive the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer. |
mMaxDequeuedBufferCount |
producer端一次最大dequeue的buffer数量,默认为1,producer端可以通过setMaxDequeuedBufferCount函数修改此值。 |
mBufferHasBeenQueued |
当一个buffer被queue进buffer queue时,会将此值设置为true。当因某种原因使得所有buffer都被free时,此值会被重置。 |
mFrameCounter |
每当queueBuffer或buffer allocation成功时,这个值都会增长 |
mTransformHint |
用于优化屏幕旋转 |
mSidebandStream |
a handle to the sideband buffer stream |
mIsAllocating |
表示一个producer是否正在分配buffers,当该变量值为true时,producer不应该修改任何FREE状态的slot。当此变量值变成false时,mIsAllocatingCondition会被signaled,表明producer已经分配完buffer。 |
mIsAllocatingCondition |
与mIsAllocating配合使用 |
mAllowAllocation |
用来决定dequeueBuffer操作时是否可以分配新的buffer |
mBufferAge |
tracks the age of the contents of the most recently dequeued buffer as the number of frames that have elapsed since it was last queued |
mGenerationNumber |
stores the current generation number of the attached producer. Any attempt to attach a buffer with a different generation number will fail. |
mAsyncMode |
指示异步模式是否被开启。在异步模式中,需要分配额外的buffer以保证producer在enqueue buffer时不被blocking。 |
mSharedBufferMode |
indicates whether or not shared buffer mode is enabled. |
mAutoRefresh |
若为enabled,表示即使BufferQueue没有通知buffer已经准备好了,consumer也应该自动acquire buffer, |
mSharedBufferSlot |
当sharedBufferMode开启后,该变量用来跟踪哪个slot包含了shared buffer。 |
mLastQueuedSlot |
最后一次被queue的buffer的序号 |
mUniqueId |
唯一的标识ID |
mSharedBufferCache |
shared buffer的Cached data |