Surface系统-4-BLASTBufferQueue和Surface的创建

718 阅读13分钟

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。

                        -- 服装学院的IT男

Surface系统-1-应用与SurfaceFlinger建立链接

Surface系统-2-SurfaceControl的创建(java层)

Surface系统-3-SurfaceControl的创建(native层)

Surface系统-4-BLASTBufferQueue和Surface的创建

Surface系统-5-BLASTBufferQueue工作流程概览

本篇同时已收录于Activity短暂的一生系列

正文

之前留下3个问题:

    1. SurfaceControl 和 Surface 对应的 native 创建逻辑
    1. BLASTBufferQueue 的 native 创建逻辑,和 SurfaceControl 有什么联系
    1. BLASTBufferQueue::nativeGetSurface 获取的 Surface 流程

本篇分析 native 层 BLASTBufferQueue 和 Surface 的创建逻辑,也就是后面2个问题。

# ViewRootImpl

    // 成员变量
    public final Surface mSurface = new Surface();
    private final SurfaceControl mSurfaceControl = new SurfaceControl();

    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {
                ......
                // 作为参数传递到 system_sertvice 进程
                relayoutResult = mWindowSession.relayout(......, mSurfaceControl,......);
                ......
                    //  给 mSurface 赋值
                    if (!useBLAST()) {
                        // 旧版本
                        mSurface.copyFrom(mSurfaceControl);
                    } else {
                        // 新版本
                        updateBlastSurfaceIfNeeded();
                    }
                ......
            }

BLAST 算是一个新特性,用于 Surface 同步场景,现在高版本都是支持的,在分析新版的流程前,还是有必要学习一下之前的 mSurface 赋值逻辑。 之前的逻辑更接近 google 原始的 Surface 设计思想,同时也简单便于理解,对于分析现在新的实现逻辑也有帮助。

1. 旧版本 Surface 的创建

旧版本的调用是 “mSurface.copyFrom(mSurfaceControl);” ,从 mSurfaceControl 里赋值给 “mSurface ,已知 mSurfaceControl 经过 relayoutWindow 流程后已经在 native 层有对应的值了,而且还创建好了 Layer 。

另外分析 native 层的 SurfaceControl 知道其内部还有个 mSurfaceData 变量代表一个 Surface ,不过还没看到这个 Surface 创建的地方。

# Surface.java

    public void copyFrom(SurfaceControl other) {
        if (other == null) {
            throw new IllegalArgumentException("other must not be null");
        }
        // 从参数获取 SurfaceControl 对象的指针 mNativeObject
        long surfaceControlPtr = other.mNativeObject;
        if (surfaceControlPtr == 0) {
            // 为空则抛异常
            throw new NullPointerException(
                    "null SurfaceControl native object. Are you using a released SurfaceControl?");
        }

        // 通过 SurfaceControl 创建一个新的 native 层 Surface 对象
        // 返回值是新对象的指针 newNativeObject
        long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
        // 将新的 newNativeObject 设置给当前 java 层 Surface
        updateNativeObject(newNativeObject);
    }

简而言之:通过 SurfaceControl 拿到(创建)一个 native 层的 Surface ,返回指针设置给当前 java 层的 Surface 。

# android_view_Surface.cpp
    static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
            jlong nativeObject, // surface 指针
            jlong surfaceControlNativeObj) { // surfaceControl 指针
        // 拿到原来对应的 Surface 对象
        Surface* self(reinterpret_cast<Surface *>(nativeObject));
        // 拿到 SurfaceControl
        sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));

        // If the underlying IGBP's are the same, we don't need to do anything.
        // 如果底层的 `IGraphicBufferProducer` 相同,则不需要做任何处理
        // 不过之前并没有创建过,所以肯定不满足这个条件
        if (self != nullptr &&
                IInterface::asBinder(self->getIGraphicBufferProducer()) ==
                IInterface::asBinder(ctrl->getIGraphicBufferProducer())) {
            return nativeObject;
        }
        // * 通过 SurfaceControl 获取一个 Surface ,如果没有内部则会新建
        sp<Surface> surface(ctrl->getSurface());
        if (surface != NULL) {
            surface->incStrong(&sRefBaseOwner);
        }
        // 返回 surface 指针给 java 层
        return reinterpret_cast<jlong>(surface.get());
    }

对于当前逻辑 java 层的 Surface 原来是没有 native 层 Surface 指针的,所以这里会走 SurfaceControl::getSurface 来新建一个 Surface 返回给 java 层。

# SurfaceControl.cpp

    sp<Surface> SurfaceControl::getSurface()
    {
        Mutex::Autolock _l(mLock);
        if (mSurfaceData == nullptr) {
            // 无值则新建
            return generateSurfaceLocked();
        }
        // 返回
        return mSurfaceData;
    }

可以看到返回的就是 mSurfaceData 这个 Surface 。如果没有值的话就会通过 SurfaceControl::generateSurfaceLocked 新建一个 Surface

# SurfaceControl.cpp

    sp<Surface> SurfaceControl::generateSurfaceLocked()
    {
        uint32_t ignore;
        auto flags = mCreateFlags & (ISurfaceComposerClient::eCursorWindow |
                                    ISurfaceComposerClient::eOpaque);
        // 1. 创建了一个名为 "bbq-wrapper" 的 SurfaceControl
        mBbqChild = mClient->createSurface(String8("bbq-wrapper"), 0, 0, mFormat,
                                        flags, mHandle, {}, &ignore);
        // 2. 通过 mBbqChild 这个 SurfaceControl 创建出一个 BLASTBufferQueue
        // BLASTBufferQueue 用于向内部队列发送帧,以便SurfaceFlinger将其显示在屏幕上
        mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);

        // This surface is always consumed by SurfaceFlinger, so the
        // 3. 从BLASTBufferQueue中 获取 Surface 对象,并将其存储在 mSurfaceData 变量中,最后返回
        mSurfaceData = mBbq->getSurface(true);

        return mSurfaceData;
    }
    1. 创建出一个孩子 SurfaceControl
    1. 使用 mBbqChild 创建出一个 BLASTBufferQueue
    1. 通过 BLASTBufferQueue::getSurface 创建一个 Surface 赋值给 mSurfaceData

这里的套路和后面要介绍的新版本 Surface 创建逻辑类似,留个印象。 需要注意 BLASTBufferQueue::getSurface 传递的参数是 true ,新版本传递的 false ,这个参数表现即将新建的 Surface 和 SurfaceControl 是不是有关系。

1.1 创建 Surface

# BLASTBufferQueue.cpp

    sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
        std::lock_guard _lock{mMutex};
        // SurfaceControl 句柄
        sp<IBinder> scHandle = nullptr;
        // includeSurfaceControlHandle 传递的 false
        if (includeSurfaceControlHandle && mSurfaceControl) {
            // 获取到 SurfaceControl 句柄
            scHandle = mSurfaceControl->getHandle();
        }
        // 创建一个 BBQSurface
        return new BBQSurface(mProducer, true, scHandle, this);
    }

这里创建了一个 BBQSurface ,BBQSurface 的父类也是 Surface

# BLASTBufferQueue.cpp

    BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
               const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
          : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {......}
# Surface.cpp
    Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp,
                    const sp<IBinder>& surfaceControlHandle)
        : mGraphicBufferProducer(bufferProducer),.... {
        ......
        mSurfaceControlHandle = surfaceControlHandle;
        ......
    }

给成员变量 mSurfaceControlHandle 赋值。

如果 BLASTBufferQueue::getSurface 传递的是 false 则新建的 BBQSurface 的 mSurfaceControlHandle 就为 null 。 稍后要分析的新版本逻辑传递的就是 false 。

2. 新版本 BLASTBufferQueue 和 Surface 的创建

在旧版本的逻辑里,也创建了 BLASTBufferQueue 对象,最后是通过 BLASTBufferQueue::getSurface 来创建一个 BBQSurface 。 新版本的逻辑也差不多,先看 java 层 BLASTBufferQueue 的构造方法。

# BLASTBufferQueue.java

    public long mNativeObject; // BLASTBufferQueue*

    /** Create a new connection with the surface flinger. */
    public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height,
            @PixelFormat.Format int format) {
        // 构建
        this(name, true /* updateDestinationFrame */);
        // 更新
        update(sc, width, height, format);
    }

    public BLASTBufferQueue(String name, boolean updateDestinationFrame) {
        // native 创建,上层保存指针
        mNativeObject = nativeCreate(name, updateDestinationFrame);
    }

    /**
     * Updates {@link SurfaceControl}, size, and format for a particular BLASTBufferQueue
     * @param sc The new SurfaceControl that this BLASTBufferQueue will update
     * @param width The new width for the buffer.
     * @param height The new height for the buffer.
     * @param format The new format for the buffer.
     */
    public void update(SurfaceControl sc, int width, int height, @PixelFormat.Format int format) {
        nativeUpdate(mNativeObject, sc.mNativeObject, width, height, format);
    }

之前的分析在 ViewRootImpl 调用的是4个参数的构构方法

    1. 触发 native 构造
    1. 执行 update 与 SurfaceControl 建立联系,并且更新相关数据

这里看到 nativeCreate 只是创建了一个 BLASTBufferQueue 并没有用到相关的参数,所以需要再执行 nativeUpdate 把相关参数应用上。

2.1 BLASTBufferQueue 的创建

# android_graphics_BLASTBufferQueue.cpp

static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName,
                          jboolean updateDestinationFrame) {
    ScopedUtfChars name(env, jName);
    // 创建对象
    sp<BLASTBufferQueue> queue = new BLASTBufferQueue(name.c_str(), updateDestinationFrame);
    queue->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(queue.get());
}
# BLASTBufferQueue.cpp

    BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
        : mSurfaceControl(nullptr), // mSurfaceControl为nullptr
            mSize(1, 1), // 大小为1
            mRequestedSize(mSize),
            mFormat(PIXEL_FORMAT_RGBA_8888), // 像素格式RGBA_8888  
            mTransactionReadyCallback(nullptr), // null
            mSyncTransaction(nullptr),
            mUpdateDestinationFrame(updateDestinationFrame) {
            // * 1. 创建 BufferQueueCore BBQBufferQueueProducer 和 BufferQueueConsumer
            createBufferQueue(&mProducer, &mConsumer);
            mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
            // safe default, most producers are expected to override this
            // 设置可以同时从队列中出队的缓冲区数量为2  
            mProducer->setMaxDequeuedBufferCount(2);
            // 2 创建 BLASTBufferItemConsumer
            mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
                                                        GraphicBuffer::USAGE_HW_COMPOSER |
                                                                GraphicBuffer::USAGE_HW_TEXTURE,
                                                        1, false, this);
            ......
            // 注意*  
            mBufferItemConsumer->setFrameAvailableListener(this);
            ......
        }

BLASTBufferQueue 的构造方法几个成员变量的值基本上都是空,这也简介说明了后续为什么要执行 “update”。 在这主要是创建了4个核心类的实例,分为2步:

    1. 在 createBufferQueue 方法里创建 BufferQueueCore BBQBufferQueueProducer 和 BufferQueueConsumer
    1. 创建 BLASTBufferItemConsumer

另外还有一个设置了帧可用的回调为 BLASTBufferQueue ,也就是当应用绘制完后会触发 BLASTBufferQueue::onFrameAvailable 来告知消费者(mBufferItemConsumer)可以拿去做下一步处理了。

2.2 构建 BufferQueueCore、BBQBufferQueueProducer、BufferQueueConsumer

# BLASTBufferQueue.cpp

    void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                                            sp<IGraphicBufferConsumer>* outConsumer) {
        // gbp,gbc 必须有值
        LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
        LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");
        // 1. 创建 BufferQueueCore
        sp<BufferQueueCore> core(new BufferQueueCore());
        LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
        // 2. 创建 BBQBufferQueueProducer
        sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
        LOG_ALWAYS_FATAL_IF(producer == nullptr,
                            "BLASTBufferQueue: failed to create BBQBufferQueueProducer");
        // 3. 创建 BufferQueueConsumer
        sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
        consumer->setAllowExtraAcquire(true);
        LOG_ALWAYS_FATAL_IF(consumer == nullptr,
                            "BLASTBufferQueue: failed to create BufferQueueConsumer");
        // bgp,gbc 赋值出参
        *outProducer = producer;
        *outConsumer = consumer;
    }

先创建了 BufferQueueCore,然后将其作为参数创建了 BBQBufferQueueProducer 和 BufferQueueConsumer ,这2个对象作为出参,也就是 BLASTBufferQueue 下的mProducer 和 mConsumer 的值。

# BLASTBufferQueue.h

    class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener {
    public:
        ......
        void onFrameAvailable(const BufferItem& item) override;
        ......
    private:
        ......
        sp<SurfaceControl> mSurfaceControl GUARDED_BY(mMutex);
        sp<IGraphicBufferConsumer> mConsumer;
        sp<IGraphicBufferProducer> mProducer;
        sp<BLASTBufferItemConsumer> mBufferItemConsumer;
        ......

    }

2.2.1 BufferQueueCore

头文件如下:

# BufferQueueCore.h

    class BufferQueueCore : public virtual RefBase {
        // 2个友元类
        friend class BufferQueueProducer;
        friend class BufferQueueConsumer;
        ......
    private:
        ......

        // 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;

        // mQueue is a FIFO of queued buffers used in synchronous mode.
        Fifo mQueue;

        // mFreeSlots contains all of the slots which are FREE and do not currently
        // have a buffer attached.
        std::set<int> mFreeSlots;

        // mFreeBuffers contains all of the slots which are FREE and currently have
        // a buffer attached.
        std::list<int> mFreeBuffers;

        // mUnusedSlots contains all slots that are currently unused. They should be
        // free and not have a buffer attached.
        std::list<int> mUnusedSlots;

        // mActiveBuffers contains all slots which have a non-FREE buffer attached.
        std::set<int> mActiveBuffers;
    }
  1. 友元类: 可以访问类的有和保护成员,也就是说 BufferQueueProducer 和 BufferQueueConsumer 这2个类可以访问 BufferQueueCore 下的私有方法

  2. mSlots:

    一个 BufferSlot 数组,大小为 NUM_BUFFER_SLOTS( 64个)。 BufferSlot 主要是用来绑定 GraphicBuffer 的,一个 BufferSlot 绑定一个 GraphicBuffer

  3. mQueue 一个队列,存放图像消费者提交的 GraphicBuffer,不过 这个队列的元素的BufferItem,GraphicBuffer,不过将被包装在BufferItem再入队

  4. mFreeSlots 一个集合,所有当前为空闲状态且没有绑定 GraphicBuffer 的 BufferSlot

  5. mFreeBuffers 一个集合,所有当前为空闲状态但已绑定 GraphicBuffer 的 BufferSlot

  6. mUnusedSlots 一个集合,当前没有使用的 BufferSlot

  7. mActiveBuffers 一个集合,BufferSlot 状态不为 FREE,并且绑定了 GraphicBuffer 的 BufferSlot

上面对几个变量的解释都是结合注释的,这里出现了 BufferSlot 和 GraphicBuffer 的概念。

BufferQueueCore 这个类里最重要的就是这几个集合,存储记录了 GraphicBuffer 的使用信息。

BufferSlot 存的 BufferSlot , mFreeSlots,mUnusedSlots,mActiveBuffers 存的是对应的角标。

生产消费者模型中 BufferQueueCore 是核心角色,里面的集合的使用模式也很重要。

2.2.1.1 BufferSlot,GraphicBuffer 相关

以第一个出现的变量 mSlots 变量为入口,SlotsType 类的定义如下:

# BufferQueueDefs.h
    namespace android {
        class BufferQueueCore;
        namespace BufferQueueDefs {
            // NUM_BUFFER_SLOTS = 64
            typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
        } 
    } 

所以mSlots是一个 长度为64的数组,内部元素是BufferSlot,BufferSlot头文件如下:

# BufferSlot.h
    struct BufferSlot {

        BufferSlot()
        : mGraphicBuffer(nullptr),
        mEglDisplay(EGL_NO_DISPLAY),
        mBufferState(),
        ...... {
        // mGraphicBuffer points to the buffer allocated for this slot or is NULL
        // if no buffer has been allocated.
        sp<GraphicBuffer> mGraphicBuffer;
        ......
        // mBufferState is the current state of this buffer slot.
        BufferState mBufferState;
        ......
        }
    }

前面提到了 GBP,GBC 他们生产和消费的对象都是 BufferQueue 中的 buff ,那么这个 buff 其实就是 GraphicBuffer ,可以将 GraphicBuffer 理解为携带图像信息的一个数据结构 BufferState 代表当前槽位 GraphicBuffer 的状态,在其源码里有详细的注释,这里对5个状态做简单介绍,后面代码会介绍实际切换状态的地方。

FREE: 该 buffer 是空闲的,可用的 owner :BufferQueue 当应用程序需要一个新的 buffer 来绘图时,它首先会尝试从 DEQUEUED 状态中获取一个 buffer。如果 DEQUEUED 状态的 buffer 不足,则会从 FREE 状态的 buffer 中申请一个新的 buffer。 DEQUEUED: 已经被dequeue,正在被应用程序绘制使用 owner : 应用程序 SurfaceFlinger和BufferQueue目前不能操作这个buff QUEUED: 该 buffer 已经由应用程序绘图完成,执行了queue. 可以被 acquired owner :BufferQueue ACQUIRED: 可以被拿去给SurfaceFlinger合成了 owner :Consumer SHARED: 该 buffer 是共享的,可能被多个应用程序或进程使用

2.2.2 BBQBufferQueueProducer

# BLASTBufferQueue.cpp

class BBQBufferQueueProducer : public BufferQueueProducer {
public:
    // 接受 BufferQueueCore 和 BLASTBufferQueue
    BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
          : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
            mBLASTBufferQueue(std::move(bbq)) {}
    ......
}
private:
    const wp<BLASTBufferQueue> mBLASTBufferQueue;

BBQBufferQueueProducer本质上还是BufferQueueProducer只是多了层封装而已。所以后续还是以 BGP 来简称。

看一下头文件的定义

# BufferQueueProducer.h

    class BufferQueueProducer : public BnGraphicBufferProducer,
                                private IBinder::DeathRecipient {
    public:
        ......
        // 取一块 buff 给生产者绘制
        virtual status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence, uint32_t width,
                                    uint32_t height, PixelFormat format, uint64_t usage,
                                    uint64_t* outBufferAge,
                                    FrameEventHistoryDelta* outTimestamps) override;
        ......
        // 消费者绘制完成,放回 BufferQueue
        virtual status_t queueBuffer(int slot,
                const QueueBufferInput& input, QueueBufferOutput* output);
        ......
    private:
        ......
        // 持有的 BufferQueueCore 对象
        sp<BufferQueueCore> mCore;
        ......
        // 指向 BufferQueueCore 下的 mSlots
        BufferQueueDefs::SlotsType& mSlots;
        String8 mConsumerName;

    }

提供了2个方法:dequeueBuffer 和 queueBuffer ,后面分析工作流程的时候,这2个方法是核心,目前先忽略。

2.2.3 BufferQueueConsumer

# BufferQueueConsumer.cpp

    BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
        mCore(core), // BufferQueueCore
        mSlots(core->mSlots), // 指向 BufferQueueCore 下的 mSlots
        mConsumerName() {}

看一下头文件的定义:

# BufferQueueConsumer.h

    class BufferQueueConsumer : public BnGraphicBufferConsumer {

    public:
        explicit BufferQueueConsumer(const sp<BufferQueueCore>& core);
        ~BufferQueueConsumer() override;
    
    ......
    // 拿到绘制完的 buff 给消费者
    virtual status_t acquireBuffer(BufferItem* outBuffer,
        nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;
    ......
    // 消费者用完了,释放一块 buff
    virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
            const sp<Fence>& releaseFence, EGLDisplay display,
            EGLSyncKHR fence);
    ......
    private:
        sp<BufferQueueCore> mCore;

        // This references mCore->mSlots. Lock mCore->mMutex while accessing.
        BufferQueueDefs::SlotsType& mSlots;

        // This is a cached copy of the name stored in the BufferQueueCore.
        // It's updated during setConsumerName.
        String8 mConsumerName;

};

这里也有2个重要方法 acquireBuffer 和 releaseBuffer。

2.3 BLASTBufferItemConsumer 的创建

# BLASTBufferQueue.h
class BLASTBufferItemConsumer : public BufferItemConsumer {......}

关键函数在父类 BufferItemConsumer 定义。

# BufferItemConsumer.h
class BufferItemConsumer: public ConsumerBase
{
public:
    ......
    status_t acquireBuffer(BufferItem* item, nsecs_t presentWhen,
            bool waitForFence = true);
    ......
    status_t releaseBuffer(const BufferItem &item,
            const sp<Fence>& releaseFence = Fence::NO_FENCE);
    ......
    private:
        sp<IGraphicBufferConsumer> mConsumer;
    
}

还有关键变量在父类 ConsumerBase 中

# ConsumerBase.h
class ConsumerBase : public virtual RefBase,
        protected ConsumerListener {

public:
    // 定义回调
    struct FrameAvailableListener : public virtual RefBase {
        // See IConsumerListener::onFrame{Available,Replaced}
        virtual void onFrameAvailable(const BufferItem& item) = 0;
        virtual void onFrameReplaced(const BufferItem& /* item */) {}
        virtual void onFrameDequeued(const uint64_t){};
        virtual void onFrameCancelled(const uint64_t){};
        virtual void onFrameDetached(const uint64_t){};
    };
    ......
    void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);

protected:
    ......
    virtual void onFrameAvailable(const BufferItem& item) override;
    ......
    wp<FrameAvailableListener> mFrameAvailableListener;
    ......
}

2.4 BLASTBufferQueue 与 SurfaceControl 建立联系

BLASTBufferQueue 的创建逻辑主要就是创建了这几个关键类的对象实例:BLASTBufferQueue ,BufferQueueCore ,BufferQueueProducer ,BufferQueueConsumer ,BLASTBufferItemConsumer 。 相关调用链如下:

android_graphics_BLASTBufferQueue::nativeCreate
    BLASTBufferQueue::init
        BLASTBufferQueue::createBufferQueue
            BufferQueueCore::init
            BufferQueueProducer::init
            BufferQueueConsumer::init
        BLASTBufferItemConsumer::init
        BLASTBufferItemConsumer::setFrameAvailableListener   -- 回调 onFrameAvailable

现在看看另一个 JNI 方法 “nativeUpdate” 是如何将 BLASTBufferQueue 和 SurfaceControl 建立联系的。

# android_graphics_BLASTBufferQueue.cpp

    static void nativeUpdate(JNIEnv* env, jclass clazz, jlong ptr, jlong surfaceControl, jlong width,
                            jlong height, jint format) {
        sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
        queue->update(reinterpret_cast<SurfaceControl*>(surfaceControl), width, height, format);
    }

拿到 BLASTBufferQueue 执行 BLASTBufferQueue::update ,注意参数有 SurfaceControl 和宽高。

# BLASTBufferQueue.cpp

    void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
                                int32_t format) {
        ......
        // 赋值
        mSurfaceControl = surface;
        ......
        ui::Size newSize(width, height);
        // 设置大小
        if (mRequestedSize != newSize) {
            mRequestedSize.set(newSize);
            mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
            ......
        }
    }

这里传递进来的 SurfaceControl 以及宽高,都是在 relayoutWindow 流程创建的 SurfaceControl 的信息,现在通过 update 方法将其应用到 BLASTBufferQueue 中。 这样一来 BLASTBufferQueue 和 SurfaceControl 就联系起来了。

2.5 获取 Surface

之前看到在 ViewRootImpl 中通过 BlastBufferQueue.createSurface 给 ViewRootImpl 下的 mSurface 赋值,这个 mSurface 也将作为这个应用窗口 View 树的 Surface 还是非常重要的。 之前留下疑问,通过 BlastBufferQueue.createSurface 获取的 Surface 和在 relayoutWindow 创建的 Surface(Layer)是同一个吗?

其实从上一小节发现将 relayoutWindow 创建的 SurfaceControl 赋值给了 BlastBufferQueue ,那也能猜到拿到的 Surface(Layer)肯定也是同一个。

下面从代码论证这点。

# BLASTBufferQueue.java
    /**
     * @return a new Surface instance from the IGraphicsBufferProducer of the adapter.
     */
    public Surface createSurface() {
        return nativeGetSurface(mNativeObject, false /* includeSurfaceControlHandle */);
    }

注释说从 IGraphicsBufferProducer 创建一个新的 Surface 实例返回。 这里传递的第二个参数是 false,控制是否包含 SurfaceControlHandle ,也就是说这次创建的 Surface 不包含 SurfaceControl ,再直白点就是这次创建的 Surface 和 前面的 SurfaceControl 无关。 这样就符合注释“ a new Surface ”,但是也有点好奇这么一来和窗口的 SurfaceControl 好像就没关系了?

# android_graphics_BLASTBufferQueue.cpp

    static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr,
                                    jboolean includeSurfaceControlHandle) {
        sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
        return android_view_Surface_createFromSurface(env,
                                                    queue->getSurface(includeSurfaceControlHandle));
    }

看来调用的是另一个 JNI 方法。

# android_view_Surface.cpp

    jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
        // 创建 java 层的 Surface 对象 
        jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
                gSurfaceClassInfo.ctor, (jlong)surface.get());
        ......
        surface->incStrong(&sRefBaseOwner);
        return surfaceObj;
    }

创建一个 java 层的 Surface 对象返回,可以看到对应的指针是参数 surface 的。 而传进来的参数就是 BLASTBufferQueue::getSurface 创建的 BBQSurface 这个方法之前已经分析过来,区别是参数是 false,也就是新建的 BBQSurface 对象和 SurfaceControl 没关系。

3. 总结

本篇涉及到的堆栈如下:

BLASTBufferQueue::init  -- java 层
    android_graphics_BLASTBufferQueue::nativeCreate  -- JNI
        BLASTBufferQueue::init
            BLASTBufferQueue::createBufferQueue
                BufferQueueCore::init
                BufferQueueProducer::init
                BufferQueueConsumer::init
            BLASTBufferItemConsumer::init
            BLASTBufferItemConsumer::setFrameAvailableListener   -- 回调 onFrameAvailable
    android_graphics_BLASTBufferQueue::nativeUpdate -- JNI
        BLASTBufferQueue::update

BlastBufferQueue.createSurface -- java 层
    android_graphics_BLASTBufferQueue::nativeGetSurface -- JNI
        BLASTBufferQueue::getSurface
            BBQSurface::init
                Surface::init
        android_view_Surface::android_view_Surface_createFromSurface
            NewObject::init -- 创建 java 层的 Surface 对象返回

本篇主要介绍了 java 层触发 BLASTBufferQueue 创建时会触发几个 native 层对象的创建,以后会介绍这几个类在一次上帧各自的作用。

同时也确认 SurfaceControl 和 BlastBufferQueue 建立了联系,不过也有个疑问,创建的 BBQSurface 和 前面创建的 SurfaceControl 以后会不会建立起联系。

类图-GBC,GBP等成员关系图.png