在上一篇SurfaceFlinger创建Surface流程中,我们会关联到BufferQueue对GraphicBuffer的管理机制,我们这次就来分析一下它的原理。

角色扮演

       Android应用的UI显示到Display的过程中,SurfaceFlinger扮演的角色只是“Flinger”,就是定于检查Layer更新,然后计算DirtyRegion,然后将结果推送给底层显示驱动进行显示。但是在App端,Surface的内容绘制却由应用层来承担。应用层绘制UI内容都需要一个GraphicBuffer,那么Surface对GraphicBuffer的申请、绘制完毕交给SurfaceFlinger去合成然后显示,这个工作也需要一套机制去管理。所以对于GraphicBuffer的管理,Android也设计了一套机制:BufferQueue,作为SurfaceFlinger管理和消费surface的中介。

生产-消费 模型

       回顾Android SurfaceFlinger 学习之路(二)—-SurfaceFlinger概述,我们可以用这副简图表示App、BufferQueue和SurfaceFlinger的关系。

       虽说是三者的关系,但是他们所属的层却只有两个,app属于Java层,BufferQueue/SurfaceFlinger属于native层。也就是说BufferQueue也是隶属SurfaceFlinger,所有工作围绕SurfaceFlinger展开。

生产者模型

        这里IGraphicBufferProducer就是app和BufferQueue重要桥梁,GraphicBufferProducer承担着单个应用进程中的UI显示需求,与BufferQueue打交道的就是它。
        根据上一篇Surface的创建流程,我们从Surface类图分析了GraphicBufferProducer在Surface中的位置,下图也可以表示:

       BpGraphicBufferProducer是GraphicBufferProducer在客户端这边的代理对象,负责和SF交互,GraphicBufferProducer通过gbp(IGraphicBufferProducer类对象)向BufferQueue获取buffer,然后进行填充UI信息,当填充完毕会通知SF,SF知道后就对该Buffer进行下一步操作。典型的生产-消费者模式

消费者模型

       BufferQueue和SurfaceFlinger之间的通信模式如下:

       也是有一对BpGraphicBufferConsumer/BnGraphicBufferConsumer支持他们之间的信息传输。

模型实现

       上一篇创建Surface流程中,当创建Layer时候,在onFirstRef里面创建了一个生产者和消费者,并对两者进行了包装:

void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;//生产者
    sp<IGraphicBufferConsumer> consumer;//消费者
    BufferQueue::createBufferQueue(&producer, &consumer);//创建生产者和消费者
    mProducer = new MonitoredProducer(producer, mFlinger);//包装生产者
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);//包装消费者
    //设置消费者相关回调
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mSurfaceFlingerConsumer->setContentsChangedListener(this);
    mSurfaceFlingerConsumer->setName(mName);

    ......
}

       MonitoredProducer对象,这个对象只是一个代理,真正实是BufferQueueProducer类,这个对象和BufferQueueCore有关联,可以管理最多达64块的缓冲区。
       SurfaceFlingerConsumer构造函数将BufferQueueConsumer传入,并设置相关回调,以便生产者填充完GraphicBuffer然后通知Consumer消费。

Core

       所以创建生产者和消费者就是由BufferQueue来创建,我们可以看看BufferQueue的createBufferQueue函数,位于frameworks/native/libs/gui/BufferQueue.cpp:

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
        sp<IGraphicBufferConsumer>* outConsumer,
        const sp<IGraphicBufferAlloc>& allocator) {//allocator == NULL
    ......
    //创建一个BufferQueueCore,她是核心
    sp<BufferQueueCore> core(new BufferQueueCore(allocator));
    ......
    //用BufferQueueCore创建生产者
    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
    ......
    //用core创建消费者
    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    ......
    //向外面传入指针赋值
    *outProducer = producer;
    *outConsumer = consumer;
}

       所以核心都是这个BufferQueueCore,他是管理图形缓冲区的中枢。这里举一个SurfaceTexture的例子,来看看他们之间的关系:

       可以认为BufferQueueCore是一个服务中心,生产者、消费者都要通过它来管理buffer。

  • 里面有一个重要的成员数组:BufferQueueDefs::SlotsType mSlots;
  • 这个BufferSlot中有一个成员变量:sp< GraphicBuffer >mGraphicBuffer;记录这个slot所涉及的缓冲区;
  • 另一个变量BufferState mBufferState;用于跟踪这个缓冲区的状态。

       1)在BufferQueueCore类中定义了一个64项的数据mSlots,framework/native/libs/gui/BufferQueueCore.h:

// mSlots is an array of buffer slots that must be mirrored on the producer
// side. This allows buffer ownership to be transferred between the producer
// and consumer without sending a GraphicBuffer over Binder. The entire
// array is initialized to NULL at construction time, and buffers are
// allocated for a slot when requestBuffer is called with that slot's index.
BufferQueueDefs::SlotsType mSlots;

       我们看看这个mSlot定义所在的位置,位于frameworks/native/include/gui/BufferQueueDefs.h中:

namespace BufferQueueDefs {
        // BufferQueue will keep track of at most this value of buffers.
        // Attempts at runtime to increase the number of buffers past this
        // will fail.
        enum { NUM_BUFFER_SLOTS = 64 };

        typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
    } // namespace BufferQueueDefs

       我们可以看到这是一个容量大小为64的数组,因此BufferQueueCore可以管理最多64块的GraphicBuffer

       我们可以帖一幅图表示Slot的角色:

       2)BufferSlot的定义位于frameworks/native/include/gui/BufferSlot.h中:

struct BufferSlot {

    BufferSlot()
    : mEglDisplay(EGL_NO_DISPLAY),
      mBufferState(BufferSlot::FREE),
      mRequestBufferCalled(false),
      mFrameNumber(0),
      mEglFence(EGL_NO_SYNC_KHR),
      mAcquireCalled(false),
      mNeedsCleanupOnRelease(false),
      mAttachedByConsumer(false) {
    }
    // mGraphicBuffer points to the buffer allocated for this slot or is NULL
    // if no buffer has been allocated.
    sp<GraphicBuffer> mGraphicBuffer;
    // BufferState represents the different states in which a buffer slot
    // can be.  All slots are initially FREE.
    enum BufferState {
        // FREE indicates that the buffer is available to be dequeued
        // by the producer.  The buffer may be in use by the consumer for
        // a finite time, so the buffer must not be modified until the
        // associated fence is signaled.
        //
        // The slot is "owned" by BufferQueue.  It transitions to DEQUEUED
        // when dequeueBuffer is called.
        FREE = 0,

        // DEQUEUED indicates that the buffer has been dequeued by the
        // producer, but has not yet been queued or canceled.  The
        // producer may modify the buffer's contents as soon as the
        // associated ready fence is signaled.
        //
        // The slot is "owned" by the producer.  It can transition to
        // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
        DEQUEUED = 1,

        // QUEUED indicates that the buffer has been filled by the
        // producer and queued for use by the consumer.  The buffer
        // contents may continue to be modified for a finite time, so
        // the contents must not be accessed until the associated fence
        // is signaled.
        //
        // The slot is "owned" by BufferQueue.  It can transition to
        // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
        // queued in asynchronous mode).
        QUEUED = 2,

        // ACQUIRED indicates that the buffer has been acquired by the
        // consumer.  As with QUEUED, the contents must not be accessed
        // by the consumer until the fence is signaled.
        //
        // The slot is "owned" by the consumer.  It transitions to FREE
        // when releaseBuffer is called.
        ACQUIRED = 3
    };

    // mBufferState is the current state of this buffer slot.
    BufferState mBufferState;
}

       mGraphicBuffer代表一块图形缓冲区GraphicBuffer,用于应用绘制UI。
       mBufferState类型为BufferState ,BufferState 的定义也位于其中,代表图形缓冲区的几种状态:

  • FREE:buffer当前可用,可以被生产者dequeued,此时owner是BufferQueueCore,当dequeuebuffer调用时,状态可以转为dequeued。
  • DEQUEUED:buffer已经被dequeued,还没被queue或canceld,此时owner是producer。
  • QUEUED:buffer已经被生产者填充,并被queued,此时的owner是bufferQueueCore。
  • ACQUIRED:buffer已经被消费者获得,此时的owner是consumer。

       一般的buffer大致会经过FREE->DEQUEUED->QUEUED->ACQUIRED->FREE这个流程,我们下面会讲到它。

       3)在BufferQueueCore创建时候,还会创建一个GraphicBufferAlloc,并将它赋值给BufferQueueCore的mAllocator成员变量。我们可以看看BufferQueueCore的构造函数,位于framework/native/libs/gui/BufferQueueCore.cpp:

BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) ://allocator为NULL
    mAllocator(allocator),
    mMutex(),
    mIsAbandoned(false),
    mConsumerControlledByApp(false),
    mConsumerName(getUniqueName()),
    mConsumerListener(),
    mConsumerUsageBits(0),
    mConnectedApi(NO_CONNECTED_API),
    mConnectedProducerListener(),
    mSlots(),
    mQueue(),
    mOverrideMaxBufferCount(0),
    mDequeueCondition(),
    mUseAsyncBuffer(true),
    mDequeueBufferCannotBlock(false),
    mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
    mDefaultWidth(1),
    mDefaultHeight(1),
    mDefaultMaxBufferCount(2),
    mMaxAcquiredBufferCount(1),
    mBufferHasBeenQueued(false),
    mFrameCounter(0),
    mTransformHint(0),
    mIsAllocating(false),
    mIsAllocatingCondition()
{
    if (allocator == NULL) {//NULL
        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
        //请求SurfaceFlinger创建GraphicBufferAlloc
        mAllocator = composer->createGraphicBufferAlloc();
        if (mAllocator == NULL) {
            BQ_LOGE("createGraphicBufferAlloc failed");
        }
    }
}

       然后回去请求SurfaceFlinger创建一个GraphicBufferAlloc,位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中:

sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{
    //创建一个GraphicBufferAlloc对象,并赋给强指针
    sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
    return gba;
}

       因为BufferQueueCore的mAllocator 类型为IGraphicBufferAlloc,继承于IInterface,所以又是跨进程调用创建。我们下面会分析到它的。

Producer

       BufferQueueProducer是生产者的实现,需要实现IGraphicBufferProducer接口,相关方法如下:

/*
 * This class defines the Binder IPC interface for the producer side of
 * a queue of graphics buffers.  It's used to send graphics data from one
 * component to another.  For example, a class that decodes video for
 * playback might use this to provide frames.  This is typically done
 * indirectly, through Surface.
 *
 * The underlying mechanism is a BufferQueue, which implements
 * BnGraphicBufferProducer.  In normal operation, the producer calls
 * dequeueBuffer() to get an empty buffer, fills it with data, then
 * calls queueBuffer() to make it available to the consumer.
 *
 * This class was previously called ISurfaceTexture.
 */
class IGraphicBufferProducer : public IInterface
{
public:
    ......
    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
    virtual status_t queueBuffer(int slot,
            const QueueBufferInput& input, QueueBufferOutput* output) = 0;
    virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;  
    ......      
}

       这几个函数的注释写的很清楚,但是限于篇幅,没有贴出来。

       BufferQueueProducer的dequeueBuffer函数用来向BufferQueueCore申请一个空闲的slot,这个slot可能已经有缓冲区,也可能没有,如果没有缓冲区,dequeueBuffer函数会分配一块新的缓冲区。得到空闲的slot后,还需要调用requestBuffer函数来取出一块缓冲区,也是从BufferQueueCore中的mSlots数组根据index获取这个位置的slot。得到缓冲区,如果不需要了,可以使用cancelBuffer函数来释放这个slot。调用dequeueBuffer函数之后,缓冲区的拥有者是生产者,缓冲区处于DEQUEUED状态。一旦缓冲区复制数据完成,通过queueBuffer函数把缓冲区的控制权交还给BufferQueueCore,这时候缓冲区将处于QUEUED状态。这些函数的使用之处我们下面会讲到。
       BufferQueueProducer类图结构如下:

Consumer

       同样,BufferQueueConsumer是消费者的实现,需要实现IGraphicBufferConsumer接口,相关方法如下:

class IGraphicBufferConsumer : public IInterface {
public:
    ......
    virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) = 0;
    virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
            EGLDisplay display, EGLSyncKHR fence,
            const sp<Fence>& releaseFence) = 0;
    ......        
}

       注释写的很清晰,但是限于篇幅。。。

       BufferQueueConsumer类是接口IGraphicBufferComsumer的实现,是一个回调接口,如果BufferQueue中有数据准备好了通知消费者取走数据。取走数据的时候,需要调用acquireBuffer函数,将缓冲区状态变成ACQUIRED,使用完之后调用releaseBuffer函数可以吧缓冲区数据归还给BufferQueueCore,这样缓冲区就变成FREE。

那consumer怎么知道一块buffer已经填充好了

       所以我们顺着Layer的onFirstRef函数,里面还有一个对于消费者的封装:SurfaceFlingerConsumer。为了方便,我再贴一遍Layer的onFirstRef函数:

void Layer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);
    mProducer = new MonitoredProducer(producer, mFlinger);
    //创建一个SurfaceFlingerConsumer用于通知消费者消费
    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
    mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    //给消费者设置监听者
    mSurfaceFlingerConsumer->setContentsChangedListener(this);
    mSurfaceFlingerConsumer->setName(mName);

}

       为了方便起见,我们将BufferQueueConsumer和SurfaceFlingerConsumer的类图都贴出来:

       为了通知消费消费GraphicBuffer,这里提供了另外一个类ConsumerListener,位于frameworks/native/include/gui/IConsumerListener.h:

ConsumerListener() { }
    virtual ~ConsumerListener() { }

    // onFrameAvailable is called from queueBuffer each time an additional
    // frame becomes available for consumption. This means that frames that
    // are queued while in asynchronous mode only trigger the callback if no
    // previous frames are pending. Frames queued while in synchronous mode
    // always trigger the callback.
    //
    // This is called without any lock held and can be called concurrently
    // by multiple threads.
    virtual void onFrameAvailable() = 0; /* Asynchronous */

    // onBuffersReleased is called to notify the buffer consumer that the
    // BufferQueue has released its references to one or more GraphicBuffers
    // contained in its slots.  The buffer consumer should then call
    // BufferQueue::getReleasedBuffers to retrieve the list of buffers
    //
    // This is called without any lock held and can be called concurrently
    // by multiple threads.
    virtual void onBuffersReleased() = 0; /* Asynchronous */

    // onSidebandStreamChanged is called to notify the buffer consumer that the
    // BufferQueue's sideband buffer stream has changed. This is called when a
    // stream is first attached and when it is either detached or replaced by a
    // different stream.
    virtual void onSidebandStreamChanged() = 0; /* Asynchronous */
};

       两个纯虚函数,当一块buffer可以被消费时,onFrameAvailable会被调用;当BufferQueue通知consumer它已经释放其mSlot中的一个或多个GraphicBuffer的引用时,会调用onBuffersReleased。

       那么什么时候注册的这个监听呢?我们需要跟随一下SurfaceFlingerConsumer 的构造函数,位于frameworks/native/services/surfaceflinger/SurfaceFlingerConsumer.h中:

SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
        uint32_t tex)
    //调用了GLConsumer的构造函数
    : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
      mTransformToDisplayInverse(false)
{}

       我们需要继续查看GLConsumer的构造函数,位于frameworks/native/libs/gui/GLConsumer.cpp:

GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
        uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
    ConsumerBase(bq, isControlledByApp), //有调用了ConsumerBase的构造函数,猫腻应该在这里
    mCurrentTransform(0),
    mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
    mCurrentFence(Fence::NO_FENCE),
    mCurrentTimestamp(0),
    mCurrentFrameNumber(0),
    mDefaultWidth(1),
    mDefaultHeight(1),
    mFilteringEnabled(true),
    mTexName(tex),
    mUseFenceSync(useFenceSync),
    mTexTarget(texTarget),
    mEglDisplay(EGL_NO_DISPLAY),
    mEglContext(EGL_NO_CONTEXT),
    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
    mAttached(true)
{
    ST_LOGV("GLConsumer");

    memcpy(mCurrentTransformMatrix, mtxIdentity,
            sizeof(mCurrentTransformMatrix));

    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
}

       又调用了ConsumerBase的构造函数,猫腻应该在这里,我们继续查看ConsumerBase的构造函数,位于frameworks/native/libs/gui/ConsumerBase.cpp中:

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue) {
    // Choose a name using the PID and a process-unique ID.
    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());

    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
    // reference once the ctor ends, as that would cause the refcount of 'this'
    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
    // that's what we create.
    //创建监听者对象
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    //包装成一个代理
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
    //mConsumer调用consumerConnect函数,通过mConsumer,把consumerListener注册到服务者类bufferQueuecore中
    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
    if (err != NO_ERROR) {
        CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
                strerror(-err), err);
    } else {
        mConsumer->setConsumerName(mName);
    }
}

       上面代码主要工作有:
       1)创建监听者对象;
       2)包装成一个代理;
       3)mConsumer调用consumerConnect函数,通过mConsumer,把consumerListener注册到服务者类bufferQueuecore中。
       那么注册操作就在于第三部。这里BufferQueueConsumer调用consumerConnect函数,位于frameworks/native/libs/gui/BufferQueueConsumer.h中:

virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
        bool controlledByApp) {
    return connect(consumer, controlledByApp);
}

       在头文件里定义了consumerConnect函数,调用connect函数,位于frameworks/native/libs/gui/BufferQueueConsumer.cpp中:

status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    ATRACE_CALL();

    if (consumerListener == NULL) {
        BQ_LOGE("connect(C): consumerListener may not be NULL");
        return BAD_VALUE;
    }

    BQ_LOGV("connect(C): controlledByApp=%s",
            controlledByApp ? "true" : "false");

    Mutex::Autolock lock(mCore->mMutex);

    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect(C): BufferQueue has been abandoned");
        return NO_INIT;
    }
    //这里把consumerListener注册到服务者类bufferQueuecore中
    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;

    return NO_ERROR;
}

       connect连接,经过层层调用,把listener监听注册到bufferQueuecore中,
这样bufferQueuecore就可以利用这个监听通知到具体的消费者。

       接着就是设置监听者:mSurfaceFlingerConsumer->setContentsChangedListener(this);我们可以看看他的操作:

void SurfaceFlingerConsumer::setContentsChangedListener(
        const wp<ContentsChangedListener>& listener) {
    //调用了ConsumerBase的setFrameAvailableListener函数
    setFrameAvailableListener(listener);
    Mutex::Autolock lock(mMutex);
    mContentsChangedListener = listener;
}
/**ConsumerBase的setFrameAvailableListener函数**/
void ConsumerBase::setFrameAvailableListener(
        const wp<FrameAvailableListener>& listener) {
    CB_LOGV("setFrameAvailableListener");
    Mutex::Autolock lock(mMutex);
    mFrameAvailableListener = listener;
}

       这样就构成了完整的监听者模式了,有Observer,也有Observable。

       这样就清楚了buffer的生产者,消费者,管理者之间的关系。

Chris Simmonds老爷子的话,就是如下内容:

  • Mechanism for passing GraphicBuffers to SurfaceFlinger
  • Contains an array of between 2 and 64 GraphicBuffers
  • Uses interface IGraphicBufferAlloc to allocate buffers (see later)
  • Provides two Binder interfaces:
  • IGraphicBufferProducer for the client (Activity)
  • IGraphicBufferConsumer for the consumer (SurfaceFlinger)
  • Buffers cycle between producer and consumer

分配图形缓冲区

       首先buffer是共享缓冲区,故肯定会涉及到互斥锁,所以buffer的状态也有很多种,一般buffer大致会经过FREE->DEQUEUED->QUEUED->ACQUIRED->FREE这个过程。如果所示:

       或者这样表示这个过程:

申请图形缓冲区

       前面看到,bufferqueuecore中mSlots数组管理缓冲区,最大容量是64,这个mSlots一开始静态分配了64个bufferslot大小的空间,但是其中的数据缓冲区不是一次性分配的,不然就太浪费空间了,所以缓冲区的空间分配是动态的,具体就是producer在dequeuebuffer时,如果没有获取到可用的缓冲区,那就要重新分配空间了。

       分配图形缓冲区,即GraphicBuffer,我们需要查看BufferQueueProducer的dequeuebuffer函数:

status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
        sp<android::Fence> *outFence, bool async,
        uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
    ATRACE_CALL();
    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        mConsumerName = mCore->mConsumerName;
    } // Autolock scope

    BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
            async ? "true" : "false", width, height, format, usage);
    //宽高不正常,则返回失败
    if ((width && !height) || (!width && height)) {
        BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
        return BAD_VALUE;
    }
    //一些变量赋初值
    status_t returnFlags = NO_ERROR;
    EGLDisplay eglDisplay = EGL_NO_DISPLAY;
    EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
    bool attachedByConsumer = false;

    { // Autolock scope
        Mutex::Autolock lock(mCore->mMutex);
        //如果正在申请Grabuffer,则要wait。里面是一个mIsAllocating标志位判断,如果为true则要等待
        mCore->waitWhileAllocatingLocked();
        //如果format为0,则赋为初值PIXEL_FORMAT_RGBA_8888
        if (format == 0) {
            format = mCore->mDefaultBufferFormat;
        }

        // Enable the usage bits the consumer requested
        usage |= mCore->mConsumerUsageBits;

        int found;//先在mSlot数组中查找FREE状态的slot,如果找到了就返回这个slot中的index。
        status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
                &found, &returnFlags);
        if (status != NO_ERROR) {
            return status;
        }

        // This should not happen
        //这种情况一般不会发生,因为如何found是INVALID_BUFFER_SLOT状态,上面的status就不会是NO_Error,就不会走到这里
        if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
            BQ_LOGE("dequeueBuffer: no available buffer slots");
            return -EBUSY;
        }
        //将找到的slot的index赋给外面传入的outSlot指向内容
        *outSlot = found;
        ATRACE_BUFFER_INDEX(found);

        attachedByConsumer = mSlots[found].mAttachedByConsumer;

        const bool useDefaultSize = !width && !height;
        if (useDefaultSize) {
            width = mCore->mDefaultWidth;
            height = mCore->mDefaultHeight;
        }
        //改变BufferState状态为DEQUEUED
        mSlots[found].mBufferState = BufferSlot::DEQUEUED;
        //然后将返回index的slot的Graphicbuffer赋给buffer变量
        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
        //判断这个GraphicBuffer是否需要重新分配空间,判断条件就是buffer为空,因为它初始值是null,第一次使用它需要分配空间,
        //如果不为null,但是buffer的width、height、format、usage属性跟要求的不一致,也要重新分配
        if ((buffer == NULL) ||
                (static_cast<uint32_t>(buffer->width) != width) ||
                (static_cast<uint32_t>(buffer->height) != height) ||
                (static_cast<uint32_t>(buffer->format) != format) ||
                ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
        {
            //如果需要重新分配GraphicBuffer,先初始化这些变量
            mSlots[found].mAcquireCalled = false;
            mSlots[found].mGraphicBuffer = NULL;
            mSlots[found].mRequestBufferCalled = false;
            mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[found].mFence = Fence::NO_FENCE;
            //增加BUFFER_NEEDS_REALLOCATION标志,已重新分配GraphicBuffer
            returnFlags |= BUFFER_NEEDS_REALLOCATION;
        }

        if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
            BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
                    "slot=%d w=%d h=%d format=%u",
                    found, buffer->width, buffer->height, buffer->format);
        }
        //给一些临时变量赋值
        eglDisplay = mSlots[found].mEglDisplay;
        eglFence = mSlots[found].mEglFence;
        *outFence = mSlots[found].mFence;
        //给fence变量赋初值
        mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
        mSlots[found].mFence = Fence::NO_FENCE;
    } // Autolock scope
    //如果需要重新分配GraphicBuffer
    if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
        status_t error;
        BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
        //需要重新分配,调用BufferQueueCore中的GraphicBufferAlloc中函数createGraphicBuffer,生成一个newGraphicBuffer
        sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                    width, height, format, usage, &error));
        if (graphicBuffer == NULL) {
            BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
            return error;
        }

        { // Autolock scope
            Mutex::Autolock lock(mCore->mMutex);

            if (mCore->mIsAbandoned) {
                BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
                return NO_INIT;
            }
            新分配的buffer,将slot的mFrameNumber 置为最大。mFrameNumber 用于LRU排序
            mSlots[*outSlot].mFrameNumber = UINT32_MAX;
            //将分配的buffer赋给slot中的mGraphicBuffer 
            mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
        } // Autolock scope
    }

    if (attachedByConsumer) {
        returnFlags |= BUFFER_NEEDS_REALLOCATION;
    }
    //如果eglFence不等于EGL_NO_SYNC_KHR。Fence我们后面会讲到,一种围栏机制
    if (eglFence != EGL_NO_SYNC_KHR) {
        //等待Buffer状态就绪,然后fence围栏放行
        EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
                1000000000);
        // If something goes wrong, log the error, but return the buffer without
        // synchronizing access to it. It's too late at this point to abort the
        // dequeue operation.
        if (result == EGL_FALSE) {
            BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
                    eglGetError());
        } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
            BQ_LOGE("dequeueBuffer: timeout waiting for fence");
        }
        eglDestroySyncKHR(eglDisplay, eglFence);
    }

    BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
            *outSlot,
            mSlots[*outSlot].mFrameNumber,
            mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);

    return returnFlags;
}

       代码虽然多,但是逻辑不复杂,我们分步查看:

       1)先在mSlot数组中查找FREE状态的slot,如果找到了就返回这个slot中的index。这个操作是调用了waitForFreeSlotThenRelock函数,我们看看这个函数的实现:

status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
        bool async, int* found, status_t* returnFlags) const {
    bool tryAgain = true;//默认是true
    while (tryAgain) {
        if (mCore->mIsAbandoned) {//如果没有初始化,BufferQueue被abandoned
            BQ_LOGE("%s: BufferQueue has been abandoned", caller);
            return NO_INIT;
        }
        //getMaxBufferCountLocked returns the maximum number of buffers that can be allocated at once
        //注释还有一些,不贴了。就是获取一次申请的buffer的最大值。查看了代码,就是所有状态的buffer个数。
        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
        //如果async为true,即异步操作,并且mOverrideMaxBufferCount不为0
        //(一般mOverrideMaxBufferCount是在BufferQueueProducer调用setBufferCount函数改变,
        //这个函数会更新mSlot中所有Slot的状态为未分配的,并把ower还给BufferQueue)
        if (async && mCore->mOverrideMaxBufferCount) {
            // FIXME: Some drivers are manually setting the buffer count
            // (which they shouldn't), so we do this extra test here to
            // handle that case. This is TEMPORARY until we get this fixed.
            //因为是异步的关系,一些驱动会修改buffer count,但是返回不及时,所以这两个值可能不相等
            if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
                BQ_LOGE("%s: async mode is invalid with buffer count override",
                        caller);
                return BAD_VALUE;
            }
        }
        
        // Free up any buffers that are in slots beyond the max buffer count
        //释放所有超出buffer数组最大数64的buffer
        for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
            assert(mSlots[s].mBufferState == BufferSlot::FREE);
            if (mSlots[s].mGraphicBuffer != NULL) {
                mCore->freeBufferLocked(s);
                *returnFlags |= RELEASE_ALL_BUFFERS;
            }
        }

        // Look for a free buffer to give to the client
        //开始查找FREE状态的Buffer,并返回
        *found = BufferQueueCore::INVALID_BUFFER_SLOT;
        int dequeuedCount = 0;
        int acquiredCount = 0;
        for (int s = 0; s < maxBufferCount; ++s) {
            switch (mSlots[s].mBufferState) {
                case BufferSlot::DEQUEUED:
                    ++dequeuedCount;//DEQUEUED + 1
                    break;
                case BufferSlot::ACQUIRED:
                    ++acquiredCount;//ACQUIRED + 1
                    break;
                case BufferSlot::FREE:
                    // We return the oldest of the free buffers to avoid
                    // stalling the producer if possible, since the consumer
                    // may still have pending reads of in-flight buffers
                    //返回最老的FREE buffer,为了避免当consumer还在等待消费pending的正在起飞的buffer时候,producer突然GG了
                    if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||//第一次找到FREE buffer,会将found指针指向这个index
                            //下次来的FREE buffer,就和上此找到的buffer对比slot的mFrameNumber ,找到mFrameNumber 最小的。
                            //这个就是根绝mFrameNumber 的大小进行LRU排序,最新的就是mFrameNumber 最大的,最老的就是mFrameNumber 最小的
                            mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
                        *found = s;
                    }
                    break;
                default:
                    break;
            }
        }

        // Producers are not allowed to dequeue more than one buffer if they
        // did not set a buffer count
        //Producers 如果没有调用setBufferCount是不允许dequeue buffer的
        if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
            BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
                    "buffer count", caller);
            return INVALID_OPERATION;
        }

        // See whether a buffer has been queued since the last
        // setBufferCount so we know whether to perform the min undequeued
        // buffers check below
        //在queueBuffer调用后,mBufferHasBeenQueued会置为true
        //如果在上次setBufferCount调用后,当buffer被queue进入BufferQueue,
        //这时候需要检查undequeue的数量是否大于最小的临界值
        if (mCore->mBufferHasBeenQueued) {
            // Make sure the producer is not trying to dequeue more buffers
            // than allowed
            //总count - dequeue的count = undequeue的count
            const int newUndequeuedCount =
                maxBufferCount - (dequeuedCount + 1);
            const int minUndequeuedCount =
                mCore->getMinUndequeuedBufferCountLocked(async);
            if (newUndequeuedCount < minUndequeuedCount) {
                BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
                        "(dequeued=%d undequeued=%d)",
                        caller, minUndequeuedCount,
                        dequeuedCount, newUndequeuedCount);
                return INVALID_OPERATION;
            }
        }

        // If we disconnect and reconnect quickly, we can be in a state where
        // our slots are empty but we have many buffers in the queue. This can
        // cause us to run out of memory if we outrun the consumer. Wait here if
        // it looks like we have too many buffers queued up.
        //如果我们调用disconnect后迅速的reconnect,会出现mSlot数组为空但是mQueue队列中的BufferItem不为空
        //所以这样会造成内存耗尽的后果
        //就是判断放入mQueue中BufferItem的个数是否大于mSlot中的个数
        //mQueue是用来存放申请的缓冲区的,是一个Vector
        bool tooManyBuffers = mCore->mQueue.size()
                            > static_cast<size_t>(maxBufferCount);
        if (tooManyBuffers) {
            BQ_LOGV("%s: queue size is %zu, waiting", caller,
                    mCore->mQueue.size());
        }

        // If no buffer is found, or if the queue has too many buffers
        // outstanding, wait for a buffer to be acquired or released, or for the
        // max buffer count to change.
        //如果没有找到FREE的buffer,或者mQueue中有太多buffer占据内存未释放
        //那么等待buffer被acquired or released;
        //或者等待最大buffer个数改变
        tryAgain = (*found == BufferQueueCore::INVALID_BUFFER_SLOT) ||
                   tooManyBuffers;
        if (tryAgain) {
            // Return an error if we're in non-blocking mode (producer and
            // consumer are controlled by the application).
            // However, the consumer is allowed to briefly acquire an extra
            // buffer (which could cause us to have to wait here), which is
            // okay, since it is only used to implement an atomic acquire +
            // release (e.g., in GLConsumer::updateTexImage())
            if (mCore->mDequeueBufferCannotBlock &&
                    (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
                return WOULD_BLOCK;
            }
            //等待有buffer可以返回
            mCore->mDequeueCondition.wait(mCore->mMutex);
        }
    } // while (tryAgain)

    return NO_ERROR;
}

       代码虽然多,但是大多数都是处理特殊情况的。核心就是从现存maxBufferCount找出FREE状态的slot,然后根据LRU匹配,取出最老的slot,然后返回index给found指针内容。
       这样取出来FREE的slot(如果能找到)。
       如果所有的buffer都不是free的,则等待。

       2)将找到的buf所对应的状态修改为DEQUEUED;

       3)然后将上面查询mSlot中返回index的slot的Graphicbuffer赋给buffer变量;

       4)判断这个GraphicBuffer是否需要重新分配空间,判断条件就是buffer为空,因为它初始值是null,第一次使用它需要分配空间;如果不为null,但是buffer的width、height、format、usage属性跟要求的不一致,也要重新分配,并打上BUFFER_NEEDS_REALLOCATION标志位。

       5)如果上面的buffer为null,则需要重新分配GraphicBuffer,调用BufferQueueCore中的GraphicBufferAlloc中函数createGraphicBuffer,生成一个new GraphicBuffer。

       6)等待eglFence状态就绪。Fence机制我们以后会讲到。

创建图形缓冲区

GraphicBuffer创建

       所以上述流程的核心是GraphicBuffer的分配,我们需要沿着上面继续分析。因此最后BufferQueueProducer中的dequeueBuffer函数中调用mCore->mAllocator的createGraphicBuffer函数就是调用了GraphicBufferAlloc的createGraphicBufferAlloc函数。mAllocator的类型为sp< IGraphicBufferAlloc >,要跨进程调用SurfaceFlinger的createGraphicBufferAlloc函数,上面讲过了。

       上面刚刚说mAllocator的类型为sp< IGraphicBufferAlloc >,所以创建GraphicBuffer的函数createGraphicBuffer也需要Bp/Bn 的IPC跨进程调用过程。GraphicBuffer通过Binder传递对象是Parcel类型可序列化的,所以他要从模板类Flattenable派生。因为这个牵扯到内存缓冲区的fd传递到客户进程,所以我们放到后面讲。

       所以我们先忽略IPC过程,直接查看生成结果,位于frameworks/native/libs/gui/GraphicBufferAlloc.cpp中:

sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
        PixelFormat format, uint32_t usage, status_t* error) {
    //创建一个GraphicBuffer对象
    sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
    status_t err = graphicBuffer->initCheck();
    *error = err;
    if (err != 0 || graphicBuffer->handle == 0) {
        if (err == NO_MEMORY) {
            GraphicBuffer::dumpAllocationsToSystemLog();
        }
        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
             "failed (%s), handle=%p",
                w, h, strerror(-err), graphicBuffer->handle);
        return 0;
    }
    return graphicBuffer;
}

       上面创建一个GraphicBuffer对象,我们看看GraphicBuffer的构造函数,位于frameworks/native/libs/ui/GraphicBuffer.cpp:

GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, 
        PixelFormat reqFormat, uint32_t reqUsage)
    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
      mInitCheck(NO_ERROR), mId(getUniqueId())
{
    width  = 
    height = 
    stride = 
    format = 
    usage  = 0;
    handle = NULL;
    //这里调用了initSize函数
    mInitCheck = initSize(w, h, reqFormat, reqUsage);
}

       构造函数给一些变量赋了初值,并调用了initSize函数,我们看看这个函数:

status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format,
        uint32_t reqUsage)
{
    //获取一个GraphicBufferAllocator对象,它是个单例
    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
    //调用allocator 的alloc函数
    status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);
    if (err == NO_ERROR) {
        this->width  = w;
        this->height = h;
        this->format = format;
        this->usage  = reqUsage;
    }
    return err;
}

       先创建一个GraphicBufferAllocator的单例对象,我们先看看它的构造函数,位于frameworks/native/libs/ui/GraphicBufferAllocator.cpp中:

alloc_device_t  *mAllocDev;

GraphicBufferAllocator::GraphicBufferAllocator()
    : mAllocDev(0)
{
    hw_module_t const* module;
    //加载gralloc设备
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
    if (err == 0) {
        //打开gralloc设备
        gralloc_open(module, &mAllocDev);
    }
}

       GraphicBufferAllocator构造函数里主要是加载了gralloc设备,然后打开它,因此mAllocDev指向了Gralloc模块。这一部分可以查看Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现,Gralloc模块的加载过程、Gralloc设备的打开过程

       加载完Gralloc模块,并打开之后,接着就是分配图形缓冲区了。我们可以继续往下看看是不是,查看GraphicBufferAllocator的alloc函数:

status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
        int usage, buffer_handle_t* handle, int32_t* stride)
{
    ATRACE_CALL();
    // make sure to not allocate a N x 0 or 0 x N buffer, since this is
    // allowed from an API stand-point allocate a 1x1 buffer instead.
    if (!w || !h)
        w = h = 1;

    // we have a h/w allocator and h/w buffer is requested
    status_t err; 
    //这里内部是调用Gralloc模块中的函数gralloc_alloc来分配一块图形缓冲区
    err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);

    ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
            w, h, format, usage, err, strerror(-err));
    
    if (err == NO_ERROR) {
        Mutex::Autolock _l(sLock);
        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
        int bpp = bytesPerPixel(format);
        if (bpp < 0) {
            // probably a HAL custom format. in any case, we don't know
            // what its pixel size is.
            bpp = 0;
        }
        alloc_rec_t rec;
        rec.w = w;
        rec.h = h;
        rec.s = *stride;
        rec.format = format;
        rec.usage = usage;
        rec.size = h * stride[0] * bpp;
        list.add(*handle, rec);
    }

    return err;
}

       这里调用alloc分配了一块共享的内存缓冲区,就是我们的图形缓冲区。内部是调用Gralloc模块中的函数gralloc_alloc,可以产查看Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现,分配图形缓冲区

       这样我们GraphicBuffer的创建工作就完成了。

       既然GraphicBuffer中的缓冲区是共享内存,我们知道使用共享内存需要传递共享内存的句柄fd。下面我们看看是如何传到客户进程的,填掉我们上面的坑。

内存缓冲区映射到应用进程

       GraphicBuffer类是从模板类Flattenable派生,这个派生类可以通过Parcel传递,通常派生类需要重载flatten和unflatten方法,用于对象的序列化和反序列化。

       为了方便分析,我们可以看看GraphicBuffer的类图:

       上面说到mAllocator的类型为sp< IGraphicBufferAlloc >,它的创建GraphicBuffer的函数createGraphicBuffer也需要Bp/Bn 的IPC跨进程调用过程,序列化传递和反序列话取出这里用于IPC传递数据,我们可以在这里看看客户端和服务端的工作流程。
       我们先看看客户端Bp端,位于frameworks/native/libs/gui/IGraphicBufferAlloc.cpp中:

class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
{
public:
    BpGraphicBufferAlloc(const sp<IBinder>& impl)
        : BpInterface<IGraphicBufferAlloc>(impl)
    {
    }
    //客户端创建图形缓冲区函数
    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
            PixelFormat format, uint32_t usage, status_t* error) {
        Parcel data, reply;
        data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
        data.writeInt32(w);
        data.writeInt32(h);
        data.writeInt32(format);
        data.writeInt32(usage);
        //通过binder驱动,执行服务端对应函数。这里服务端是将创建的GraphicBuffer序列化后,塞给replay
        remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
        sp<GraphicBuffer> graphicBuffer;
        status_t result = reply.readInt32();
        if (result == NO_ERROR) {
            //创建一个空壳子
            graphicBuffer = new GraphicBuffer();
            //然后客户端从服务端(SurfaceFlinger)返回的序列化后的replay,
            //反序列化出Graphicbuffer,放入空壳子中
            result = reply.read(*graphicBuffer);
            // reply.readStrongBinder();
            // here we don't even have to read the BufferReference from
            // the parcel, it'll die with the parcel.
        }
        *error = result;
        return graphicBuffer;
    }
};

       客户端这里主要通过binder驱动,取出从服务端返回的序列化后的对象replay,然后自己造一个空壳子,然后读取replay信息,反序列化出GraphicBuffer。

       那么服务端(SurfaceFlinger)创建GraphicBuffer并反序列化就在Bn端,我们看看Bn端实现,同样位于位于frameworks/native/libs/gui/IGraphicBufferAlloc.cpp中:

status_t BnGraphicBufferAlloc::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // codes that don't require permission check

    /* BufferReference just keeps a strong reference to a
     * GraphicBuffer until it is destroyed (that is, until
     * no local or remote process have a reference to it).
     */
    class BufferReference : public BBinder {
        sp<GraphicBuffer> buffer;
    public:
        BufferReference(const sp<GraphicBuffer>& buffer) : buffer(buffer) { }
    };


    switch(code) {
        case CREATE_GRAPHIC_BUFFER: {
            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
            uint32_t w = data.readInt32();
            uint32_t h = data.readInt32();
            PixelFormat format = data.readInt32();
            uint32_t usage = data.readInt32();
            status_t error;
            //调用GraphicBufferAlloc的createGraphicBuffer函数,创建一个GraphicBuffer实例
            sp<GraphicBuffer> result =
                    createGraphicBuffer(w, h, format, usage, &error);
            reply->writeInt32(error);
            if (result != 0) {
                GraphicBuffer进行序列化,传给client
                reply->write(*result);
                // We add a BufferReference to this parcel to make sure the
                // buffer stays alive until the GraphicBuffer object on
                // the other side has been created.
                // This is needed so that the buffer handle can be
                // registered before the buffer is destroyed on implementations
                // that do not use file-descriptors to track their buffers.
                reply->writeStrongBinder( new BufferReference(result) );
            }
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

       GraphicBufferAlloc的createGraphicBuffer函数我们上面分析过了。这样就将创建的GraphicBuffer实例序列化后,在通过binder驱动传给client。

       我们知道,一个对象要在进程间传输必须继承于Flattenable类,并且实现flatten和unflatten方法,flatten方法用于序列化该对象,unflatten方法用于反序列化对象。

       上面说到GraphicBuffer中的缓冲区是共享内存,使用共享内存需要传递共享内存的句柄fd,那么这个fd的传递就应该在GraphicBuffer的序列化/反序列化中,我们就来看看这个过程。

       这里我先回顾一下Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现的内容:

       图形缓冲区可以从系统帧缓冲区分配也可以从内存中分配,分配一个图形缓冲区后还需要将该图形缓冲区映射到分配该buffer的进程地址空间来,在Android系统中,图形缓冲区的管理由SurfaceFlinger服务来负责。在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用,而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用,也可以在其它的应用程序中使用。当其它的应用程序需要使用图形缓冲区的时候,它们就会请求SurfaceFlinger服务为它们分配并将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。在从内存中分配buffer时,已经将分配的buffer映射到了SurfaceFlinger服务进程地址空间,如果该buffer是应用程序请求SurfaceFlinger服务为它们分配的,那么还需要将SurfaceFlinger服务返回来的图形缓冲区映射到应用程序进程地址空间。

       GraphicBuffer类从模板类Flattenable派生,这个派生类可以通过Parcel传递,通常派生类需要重载flatten和unflatten方法,用于对象的序列化和反序列化。

       1)将一个对象写入到Parcel中,需要使用flatten函数序列化该对象,我们先来看下flatten函数:

status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
    size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
    if (size < sizeNeeded) return NO_MEMORY;

    size_t fdCountNeeded = GraphicBuffer::getFdCount();
    if (count < fdCountNeeded) return NO_MEMORY;

    int32_t* buf = static_cast<int32_t*>(buffer);
    buf[0] = 'GBFR';
    buf[1] = width;
    buf[2] = height;
    buf[3] = stride;
    buf[4] = format;
    buf[5] = usage;
    buf[6] = static_cast<int32_t>(mId >> 32);
    buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
    buf[8] = 0;
    buf[9] = 0;

    if (handle) {
        buf[8] = handle->numFds;
        buf[9] = handle->numInts;
        native_handle_t const* const h = handle;
        //把handle中的data复制到fds中 
        memcpy(fds,     h->data,             h->numFds*sizeof(int));
        memcpy(&buf[10], h->data + h->numFds, h->numInts*sizeof(int));
    }

    buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded);
    size -= sizeNeeded;
    if (handle) {
        fds += handle->numFds;
        count -= handle->numFds;
    }

    return NO_ERROR;
}

       这个handle类型为native_handle_t ,且typedef成了buffer_handle_t,如果忘记了这一部分,可以查看Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现。我们贴一下它的定义:

typedef struct native_handle  
{  
    int version; //设置为结构体native_handle_t的大小,用来标识结构体native_handle_t的版本  
    int numFds;  //表示结构体native_handle_t所包含的文件描述符的个数,这些文件描述符保存在成员变量data所指向的一块缓冲区中。  
    int numInts; //表示结构体native_handle_t所包含的整数值的个数,这些整数保存在成员变量data所指向的一块缓冲区中。  
    int data[0]; //指向的一块缓冲区中  
} native_handle_t;

       所以我们回到flatten函数中,fds参数用来传递文件句柄,函数把handle中的表示指向图形缓冲区文件描述符句柄复制到fds中,因此这些句柄就能通过binder传递到目标进程中去。

       2)在应用程序读取来自服务进程的GraphicBuffer对象时,也就是result = reply.read(*p),会调用GraphicBuffer类的unflatten函数进行反序列化过程:

status_t GraphicBuffer::unflatten(
        void const*& buffer, size_t& size, int const*& fds, size_t& count) {
    if (size < 8*sizeof(int)) return NO_MEMORY;

    int const* buf = static_cast<int const*>(buffer);
    if (buf[0] != 'GBFR') return BAD_TYPE;

    const size_t numFds  = buf[8];
    const size_t numInts = buf[9];

    const size_t sizeNeeded = (10 + numInts) * sizeof(int);
    if (size < sizeNeeded) return NO_MEMORY;

    size_t fdCountNeeded = 0;
    if (count < fdCountNeeded) return NO_MEMORY;

    if (handle) {
        // free previous handle if any
        free_handle();
    }

    if (numFds || numInts) {
        width  = buf[1];
        height = buf[2];
        stride = buf[3];
        format = buf[4];
        usage  = buf[5];
        //创建一个native_handle对象
        native_handle* h = native_handle_create(numFds, numInts);
        //将fds复制到native_handle对象的data中,和flatten操作相反
        memcpy(h->data,          fds,     numFds*sizeof(int));
        memcpy(h->data + numFds, &buf[10], numInts*sizeof(int));
        handle = h;
    } else {
        width = height = stride = format = usage = 0;
        handle = NULL;
    }

    mId = static_cast<uint64_t>(buf[6]) << 32;
    mId |= static_cast<uint32_t>(buf[7]);

    mOwner = ownHandle;

    if (handle != 0) {
        //使用GraphicBufferMapper将服务端创建的图形缓冲区映射到当前进程地址空间  
        status_t err = mBufferMapper.registerBuffer(handle);
        if (err != NO_ERROR) {
            width = height = stride = format = usage = 0;
            handle = NULL;
            ALOGE("unflatten: registerBuffer failed: %s (%d)",
                    strerror(-err), err);
            return err;
        }
    }

    buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded);
    size -= sizeNeeded;
    fds += numFds;
    count -= numFds;

    return NO_ERROR;
}

       调用unflatten函数时,共享区的文件句柄已经准备好了,但是内存还没有进行映射,调用了mBufferMapper.registerBuffer函数来进行内存映射。
       GraphicBufferMapper是单例的模板类派生的,mBufferMapper对象在GraphicBuffer的构造函数中初始化赋值了,上面我们列出过了。我们看看GraphicBufferMapper的构造函数,位于frameworks/native/libs/ui/GraphicBufferMapper.cpp:

GraphicBufferMapper::GraphicBufferMapper()
    : mAllocMod(0)
{
    hw_module_t const* module;
    //加载gralloc模块
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
    if (err == 0) {
        将hw_module_t的指针转换为gralloc_module_t类型指针 
        mAllocMod = (gralloc_module_t const *)module;
    }
}

       这里根据模块ID加载Gralloc模块,并得到Gralloc模块的HMI符号首地址,并强制转换为gralloc_module_t类型指针。

       我们接着看下GraphicBufferMapper::registerBuffer函数:

status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
{
    ATRACE_CALL();
    status_t err;
    //将服务端创建的图形缓冲区映射到当前进程地址空间
    err = mAllocMod->registerBuffer(mAllocMod, handle);

    ALOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
            handle, err, strerror(-err));
    return err;
}

       调用了mAllocMod的registerBuffer函数,mAllocMod同样是指向了Gralloc模块的指针,因此实际是调用了Gralloc模块的gralloc_register_buffer函数。这个函数就是调用了mmap来进行共享内存的映射。
       这一部分仍然可以查看Android SurfaceFlinger 学习之路(一)—-Android图形显示之HAL层Gralloc模块实现。我们仍然回顾一下以前的内容:

       registerBuffer和unregisterBuffer分别用来注册和注销一个指定的图形缓冲区,所谓注册图形缓冲区,实际上就是将一块图形缓冲区映射到一个进程的地址空间去,而注销图形缓冲区就是执行相反的操作。lock和unlock分别用来锁定和解锁一个指定的图形缓冲区,在访问一块图形缓冲区的时候,例如,向一块图形缓冲写入内容的时候,需要将该图形缓冲区锁定,用来避免访问冲突。在锁定一块图形缓冲区的时候,可以指定要锁定的图形绘冲区的位置以及大小,这是通过参数l、t、w和h来指定的,其中,参数l和t指定的是要访问的图形缓冲区的左上角位置,而参数w和h指定的是要访问的图形缓冲区的宽度和长度。锁定之后,就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址,保存在输出参数vaddr中。另一方面,在访问完成一块图形缓冲区之后,需要解除这块图形缓冲区的锁定。

       这就是内存缓冲区映射到应用进程的过程。因为需要映射共享内存,所以必须要序列化和反序列Pracel对象。如下图:

       这里我们创建GraphicBuffer流程就分析完了。

小结

       本节主要分析GraphicBuffer的创建过程,下一节我们分析对它的管理流程。