Android14 SurfaceFlinger-BLASTBufferQueue的创建

如果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);
    }

 分为两步

1. 生成一个BLASTBufferQueue

  1. BBQ主要核心逻辑的初始化都放在了Native对象的构造函数,做了以下几件事:

  2. 创建图形缓冲区生产消费模型;
  3. 连接本地的图形缓冲区消费者;
  4. 设置图形缓冲区监听器。
   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;
}
  1. 连接本地的图形缓冲区消费者

类似于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就初始化完成了。

2.调用BufferQueue.createSurface创建一个Surface对象。

通过梳理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的句柄。

接着创建了一个BBQSurface对象。

    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类型的成员变量mBbq指向一个BLASTBufferQueue对象。还是要去看Surface的构造函数。

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 - 掘金

你可能感兴趣的:(java,开发语言)