忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。
-- 服装学院的IT男
Surface系统-1-应用与SurfaceFlinger建立链接
Surface系统-2-SurfaceControl的创建(java层)
Surface系统-3-SurfaceControl的创建(native层)
Surface系统-4-BLASTBufferQueue和Surface的创建
Surface系统-5-BLASTBufferQueue工作流程概览
本篇同时已收录于Activity短暂的一生系列
正文
之前留下3个问题:
-
- SurfaceControl 和 Surface 对应的 native 创建逻辑
-
- BLASTBufferQueue 的 native 创建逻辑,和 SurfaceControl 有什么联系
-
- 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;
}
-
- 创建出一个孩子 SurfaceControl
-
- 使用 mBbqChild 创建出一个 BLASTBufferQueue
-
- 通过 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个参数的构构方法
-
- 触发 native 构造
-
- 执行 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步:
-
- 在 createBufferQueue 方法里创建 BufferQueueCore BBQBufferQueueProducer 和 BufferQueueConsumer
-
- 创建 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;
}
-
友元类: 可以访问类的有和保护成员,也就是说 BufferQueueProducer 和 BufferQueueConsumer 这2个类可以访问 BufferQueueCore 下的私有方法
-
mSlots:
一个 BufferSlot 数组,大小为 NUM_BUFFER_SLOTS( 64个)。 BufferSlot 主要是用来绑定 GraphicBuffer 的,一个 BufferSlot 绑定一个 GraphicBuffer
-
mQueue 一个队列,存放图像消费者提交的 GraphicBuffer,不过 这个队列的元素的BufferItem,GraphicBuffer,不过将被包装在BufferItem再入队
-
mFreeSlots 一个集合,所有当前为空闲状态且没有绑定 GraphicBuffer 的 BufferSlot
-
mFreeBuffers 一个集合,所有当前为空闲状态但已绑定 GraphicBuffer 的 BufferSlot
-
mUnusedSlots 一个集合,当前没有使用的 BufferSlot
-
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 以后会不会建立起联系。