如果mWindowSession.relayout之后,mSurfaceControl将会变成有效的,此时会判断blast是否开启(blast特性时12新推出的,它默认开启的),所以进入到getOrCreateBLASTSurface,在这里将会生成一个BLASTBufferQueue, 而原来的 mSurface.copyFrom(mSurfaceControl)
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
// 生成了mSurfaceControl
relayoutResult = mWindowSession.relayout(mWindow, params,
requestedWidth, requestedHeight, viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mRelayoutSeq,
mLastSyncSeqId, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl,
mTempInsets, mTempControls, mRelayoutBundle);
if (mSurfaceControl.isValid()) {
if (!useBLAST()) {
mSurface.copyFrom(mSurfaceControl);
} else {
updateBlastSurfaceIfNeeded();
}
ViewRootImpl
void updateBlastSurfaceIfNeeded() {
if (!mSurfaceControl.isValid()) {
return;
}
if (mBlastBufferQueue != null && mBlastBufferQueue.isSameSurfaceControl(mSurfaceControl)) {
mBlastBufferQueue.update(mSurfaceControl,
mSurfaceSize.x, mSurfaceSize.y,
mWindowAttributes.format);
return;
}
// If the SurfaceControl has been updated, destroy and recreate the BBQ to reset the BQ and
// BBQ states.
if (mBlastBufferQueue != null) {
mBlastBufferQueue.destroy();
}
//第一次获取会创建BBQ
mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl,
mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format);
mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback);
// 通过BBQ创建Surface对象
Surface blastSurface = mBlastBufferQueue.createSurface();
// Only call transferFrom if the surface has changed to prevent inc the generation ID and
//BBQ已创建,则更新Buffer与Layer的几何属性
// causing EGL resources to be recreated.
mSurface.transferFrom(blastSurface);
}
分为两步
BBQ主要核心逻辑的初始化都放在了Native对象的构造函数,做了以下几件事:
frameworks/base/graphics/java/android/graphics/BLASTBufferQueue.java
/** 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) {
mNativeObject = nativeCreate(name, updateDestinationFrame);
}
frameworks/base/core/jni/android_graphics_BLASTBufferQueue.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName,
jboolean updateDestinationFrame) {
ScopedUtfChars name(env, jName);
sp queue = new BLASTBufferQueue(name.c_str(), updateDestinationFrame);
queue->incStrong((void*)nativeCreate);
return reinterpret_cast(queue.get());
}
frameworks/native/libs/gui/BLASTBufferQueue.cpp
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
: mSurfaceControl(nullptr),
mSize(1, 1),
mRequestedSize(mSize),
mFormat(PIXEL_FORMAT_RGBA_8888),
mTransactionReadyCallback(nullptr),
mSyncTransaction(nullptr),
mUpdateDestinationFrame(updateDestinationFrame) {
// 创建图形缓冲区生产消费模型
createBufferQueue(&mProducer, &mConsumer);
// since the adapter is in the client process, set dequeue timeout
// explicitly so that dequeueBuffer will block
// 由于适配器在客户端进程中,显式设置 dequeue 超时,以便 dequeueBuffer 流程阻塞
mProducer->setDequeueTimeout(std::numeric_limits::max());
// safe default, most producers are expected to override this
// 设置生产者执行一次dequeue可以获得的最大缓冲区数。
mProducer->setMaxDequeuedBufferCount(2);
mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
GraphicBuffer::USAGE_HW_COMPOSER |
GraphicBuffer::USAGE_HW_TEXTURE,
1, false, this);
static std::atomic nextId = 0;
mProducerId = nextId++;
mName = name + "#" + std::to_string(mProducerId);
auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);
mBufferItemConsumer->setName(String8(consumerName.c_str()));
// 设置当一个新的帧变为可用后会被通知的监听器对象
mBufferItemConsumer->setFrameAvailableListener(this);
// 得到SurfaceFlinger需要获取的缓冲区的数量。
ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
// 设置消费者可以一次获取的缓冲区的最大值(默认为1)。
mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
mNumAcquired = 0;
mNumFrameAvailable = 0;
TransactionCompletedListener::getInstance()->addQueueStallListener(
[&](const std::string& reason) {
std::function callbackCopy;
{
std::unique_lock _lock{mMutex};
callbackCopy = mTransactionHangCallback;
}
if (callbackCopy) callbackCopy(reason);
},
this);
BQA_LOGV("BLASTBufferQueue created");
}
void BLASTBufferQueue::createBufferQueue(sp* outProducer,
sp* outConsumer) {
LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");
//创建BufferQueue核心类,主要负责缓冲区的调度工作
sp core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
//创建生产者模型,等待图形生产者连接使用
sp producer(new BBQBufferQueueProducer(core, this));
LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BLASTBufferQueue: failed to create BBQBufferQueueProducer");
//创建消费者模型,等待图形消费者连接使用
sp consumer(new BufferQueueConsumer(core));
consumer->setAllowExtraAcquire(true);
LOG_ALWAYS_FATAL_IF(consumer == nullptr,
"BLASTBufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
}
类似于BufferQueue::createBufferQueue,但是创建了一个适配器专用的BufferQueue生产者。这个BQP允许调用客户端指定的ProducerListener并异步调用它们,模拟单向Binder调用行为。如果ProducerListener在没有它的情况下回调进入BLASTBufferQueue,我们就会死锁。
这个函数创建了三个对象,BufferQueueCore、BBQBufferQueueProducer和BufferQueueConsumer。
首先生成一个BufferQueueCore对象core,然后以这个core分别生成producer和consumer。最后将producer和consumer存入的指针指向他们。
这个core相当于一个容器,里面管理存放buffer,producer和consuer都持有这个core,这就是一个典型的生产者-消费者模型,core就是缓存仓库
BBQBufferQueueProducer
BBQBufferQueueProducer继承自BufferQueueProducer,间接就继承自BnGraphicBufferProducer 说明它工作在服务端,是真正干活的对象。它是buffer的生产者,它会从core中取空闲的buffer出来绘制,绘制完后再放回去core。即dequeueBuffer 和queueBuffer 两个方法。
class BBQBufferQueueProducer : public BufferQueueProducer {
class BufferQueueProducer : public BnGraphicBufferProducer,
class BnGraphicBufferProducer : public BnInterface
BnGraphicBufferConsumer
再来看看消费者,它是继承自BnGraphicBufferConsumer,因此也是工作的服务端直接干活的对象
class BufferQueueConsumer : public BnGraphicBufferConsumer {
private:
sp 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;
BufferQueueConsumer::BufferQueueConsumer(const sp& core) :
mCore(core),
mSlots(core->mSlots),
mConsumerName() {}
到这里ViewRootImpl的mBlastBufferQueue就初始化完成了。
通过梳理BBQ的初始化,对消费者端的大概流程有了一定的认识,接下来梳理下生产者方的代表,也就是Surface。Android 显示的的内容来源于各种绘制模块,而这些绘制模块需要与BQ建立连接,获取Buffer用以绘制,这样才能将绘制的画像通过BBQ提交给SF合成。Surface作为生产者模型与绘制模块之间桥梁,相关的流程掌握显得尤为重要。
绘制模块指的是那些图像生产者,如以使用SurfaceView、GlSurfaceView、TextureView控件为代表的Video模块、Camera模块、游戏应用等,以及使用软件绘制、硬件加速绘制为代表的普通控件。
回到创建BBQ的流程,在ViewRootImpl.getOrCreateBLASTSurface方法中,创建完BBQ,紧接着会创建Surface对象,直接看Native 对象的构造函数:
frameworks/base/graphics/java/android/graphics/BLASTBufferQueue.java
/**
* @return a new Surface instance from the IGraphicsBufferProducer of the adapter.
*/
public Surface createSurface() {
return nativeGetSurface(mNativeObject, false /* includeSurfaceControlHandle */);
}
frameworks/base/core/jni/android_graphics_BLASTBufferQueue.cpp
static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr,
jboolean includeSurfaceControlHandle) {
sp queue = reinterpret_cast(ptr);
return android_view_Surface_createFromSurface(env,
queue->getSurface(includeSurfaceControlHandle));
}
这里传入的ptr即上一节我们创建BLASTBufferQueue后,从C++层返回给Java层的BLASTBufferQueue指针,所以这里我们可以拿到上一节创建的BLASTBufferQueue对象。
接着调用BLASTBufferQueue.getSurface函数。
sp BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
std::lock_guard _lock{mMutex};
sp scHandle = nullptr;
if (includeSurfaceControlHandle && mSurfaceControl) {
scHandle = mSurfaceControl->getHandle();
}
return new BBQSurface(mProducer, true, scHandle, this);
}
这里传入的includeSurfaceControlHandle是false,所以这里的handle为空。上面分析SurfaceControl的创建流程的时候,知道SurfaceControl保存的handle是其在SurfaceFlinger处对应的Layer的句柄。
frameworks/native/libs/gui/BLASTBufferQueue.cpp
BBQSurface(const sp& igbp, bool controlledByApp,
const sp& scHandle, const sp& bbq)
: Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}
BBQSurface继承Surface,内部有一个sp
frameworks/native/libs/gui/Surface.cpp
Surface::Surface(const sp& bufferProducer, bool controlledByApp,
const sp& surfaceControlHandle)
: mGraphicBufferProducer(bufferProducer),
mSurfaceControlHandle = surfaceControlHandle;
}
可以看到构建的Surface其实是它的子类BBQSurface,这里传入参数controledByApp == true,说明它是由APP自己控制的,surfaceControlHandle == nullptr, 同时接受一个producer,说这Surface的角色是producer,由surface来产生buffer数据。 surface的dequeueBuffer和enqueueBuffer最终会调用到producer对应的方法。
dequeueBuffer
frameworks/native/libs/gui/Surface.cpp
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_FORMAT("dequeueBuffer - %s", getDebugName());
ALOGV("Surface::dequeueBuffer");
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, dqInput.width,
dqInput.height, dqInput.format,
dqInput.usage, &mBufferAge,
dqInput.getTimestamps ?
&frameTimestamps : nullptr);
}
enqueueBuffer
frameworks/native/libs/gui/Surface.cpp
int Surface::dequeueBuffers(std::vector* buffers) {
...
status_t result = mGraphicBufferProducer->dequeueBuffers(dequeueInput, &dequeueOutput);
...
}
此时我们已经通过BLASTBufferQueue.getSurface创建了一个新的Surface对象,接着调用android_view_Surface_createFromSurface函数:
需要记住的是如何生成Surface对象,它实质上是一个BBQSurface,代表者生产者。最后通过调用一个JNI函数android_view_Surface_createFromSurface来获构建一个Surface个对象,返回给JAVA层。
frameworks/base/core/jni/android_view_Surface.cpp
object android_view_Surface_createFromSurface(JNIEnv* env, const sp& surface) {
jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
gSurfaceClassInfo.ctor, (jlong)surface.get());
if (surfaceObj == NULL) {
if (env->ExceptionCheck()) {
ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
LOGE_EX(env);
env->ExceptionClear();
}
return NULL;
}
surface->incStrong(&sRefBaseOwner);
return surfaceObj;
}
这里将反射调用Surface的私有构造方法:并将BBQSurface的指针保存到Surface.mNativeObject.
frameworks/base/core/java/android/view/Surface.java
/* called from android_view_Surface_createFromIGraphicBufferProducer() */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private Surface(long nativeObject) {
synchronized (mLock) {
setNativeObjectLocked(nativeObject);
}
}
最终调用Surface.setNativeObjectLocked将C++层的Surface的地址保存在了Java层的Surface的mNativeObject中。
再次回到ViewRootImpl.void updateBlastSurfaceIfNeeded()
mSurface.transferFrom(blastSurface);
frameworks/base/core/java/android/view/ViewRootImpl.java
void updateBlastSurfaceIfNeeded() {
if (!mSurfaceControl.isValid()) {
return;
}
if (mBlastBufferQueue != null && mBlastBufferQueue.isSameSurfaceControl(mSurfaceControl)) {
mBlastBufferQueue.update(mSurfaceControl,
mSurfaceSize.x, mSurfaceSize.y,
mWindowAttributes.format);
return;
}
// If the SurfaceControl has been updated, destroy and recreate the BBQ to reset the BQ and
// BBQ states.
if (mBlastBufferQueue != null) {
mBlastBufferQueue.destroy();
}
mBlastBufferQueue = new BLASTBufferQueue(mTag, mSurfaceControl,
mSurfaceSize.x, mSurfaceSize.y, mWindowAttributes.format);
mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback);
Surface blastSurface = mBlastBufferQueue.createSurface();
// Only call transferFrom if the surface has changed to prevent inc the generation ID and
// causing EGL resources to be recreated.
mSurface.transferFrom(blastSurface);
}
frameworks/base/core/java/android/view/Surface.java
public void transferFrom(Surface other) {
if (other == null) {
throw new IllegalArgumentException("other must not be null");
}
if (other != this) {
final long newPtr;
synchronized (other.mLock) {
newPtr = other.mNativeObject;
other.setNativeObjectLocked(0);
}
synchronized (mLock) {
if (mNativeObject != 0) {
nativeRelease(mNativeObject);
}
setNativeObjectLocked(newPtr);
}
}
}
将other的mNativeObject赋值给当前Surface,并且将other的mNativeObject置为0,将other无效化。
总结:
通过分析APP与WMS和SurfaceFlinger的IPC通信,详细介绍了创建SurfaceControl以及Surface的流程
SurfaceControl持有SurfaceFlinger进程中创建的Layer的handle
Surface是通过BlastBufferQueue生成的一个BBQSurface,它继承自Surface,Surface是ANativeWindow的子类,它持有一个生产者,主要有dequeueBuffer和enqueueBuffer方法。
参考:
Android View绘制原理 - 生成Surface - 掘金