Android14 SurfaceFlinger-BLASTBufferQueue的创建

这篇具有很好参考价值的文章主要介绍了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<BLASTBufferQueue> queue = new BLASTBufferQueue(name.c_str(), updateDestinationFrame);
    queue->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(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<int64_t>::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<uint32_t> 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<void(const std::string&)> callbackCopy;
                {
                    std::unique_lock _lock{mMutex};
                    callbackCopy = mTransactionHangCallback;
                }
                if (callbackCopy) callbackCopy(reason);
            },
            this);

    BQA_LOGV("BLASTBufferQueue created");
}
void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                                         sp<IGraphicBufferConsumer>* 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<BufferQueueCore> core(new BufferQueueCore());
    LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
       //创建生产者模型,等待图形生产者连接使用

    sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
    LOG_ALWAYS_FATAL_IF(producer == nullptr,
                        "BLASTBufferQueue: failed to create BBQBufferQueueProducer");
       //创建消费者模型,等待图形消费者连接使用
    sp<BufferQueueConsumer> 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<IGraphicBufferProducer>

BnGraphicBufferConsumer

再来看看消费者,它是继承自BnGraphicBufferConsumer,因此也是工作的服务端直接干活的对象

class BufferQueueConsumer : public BnGraphicBufferConsumer {

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;



BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& 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<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
    return android_view_Surface_createFromSurface(env,
                                                  queue->getSurface(includeSurfaceControlHandle));
}

这里传入的ptr即上一节我们创建BLASTBufferQueue后,从C++层返回给Java层的BLASTBufferQueue指针,所以这里我们可以拿到上一节创建的BLASTBufferQueue对象。

接着调用BLASTBufferQueue.getSurface函数。

sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
    std::lock_guard _lock{mMutex};
    sp<IBinder> 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<IGraphicBufferProducer>& igbp, bool controlledByApp,
               const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
          : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}

BBQSurface继承Surface,内部有一个sp<BLASTBufferQueue>类型的成员变量mBbq指向一个BLASTBufferQueue对象。还是要去看Surface的构造函数。

frameworks/native/libs/gui/Surface.cpp

Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp,
                 const sp<IBinder>& 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<BatchBuffer>* 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>& 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 - 掘金文章来源地址https://www.toymoban.com/news/detail-836109.html

到了这里,关于Android14 SurfaceFlinger-BLASTBufferQueue的创建的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Vsync信号和SurfaceFlinger刷新机制;打造智能车厢的关键技术

    车载智能座舱系统在现代汽车中已经越来越常见,它可以提供各种功能,例如音乐、导航和驾驶辅助等。要实现这些功能,需要底层硬件和系统软件的支持。其中,Vsync信号和SurfaceFlinger刷新机制是车载智能座舱系统中的两个关键技术。 Vsync信号是指显示器垂直同步信号,它可

    2023年04月23日
    浏览(10)
  • Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?

    Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?

    好久不见~ 最近几个月变化挺大的,不论是自己的家庭还是社会环境,把我们能做的做好,慢慢适应新的变化,这也是一种不可或缺的能力吧! Android14 即将正式发布,作为开发者需要注意哪些内容?长话短说,一起来看看吧~ 主要分为两部分: 一是影响所有的 Android 应用,这

    2024年02月05日
    浏览(17)
  • Android权限列表(基于Android 14)

    权限的目的为了保护用户隐私,应用在访问一些敏感数据时,必须事先取得用户授权后才能使用,比如:比如读取sdcard、访问通讯录等。 在Android6.0之前的设备上,系统不会提醒用户正在获取的权限。一旦安装应用,就意味着该应用所需的所有权限均已经得到授权。在这种情

    2024年02月16日
    浏览(11)
  • Android 各版本特性(Android6-14)

    Android 各版本特性(Android6-14)

    一:介绍 Android版本对应的Api版本 二:Android 6.0 (API 23) Google I/O 2015大会如约已于2015年5月28日举行。在发布会上代号为“Marshmallow(棉花糖)”的安卓6.0系统正式推出。 Android 6.0 的API级别:23 新特性: 1.运行时权限(最主要) 此版本引入了一种新的权限模式,用户可直接在

    2024年02月07日
    浏览(11)
  • Android studio导入Android源码(AOSP Android 14)

    1. 完整编译AOSP源码 有些java文件是在编译过程中动态生成的,需要完整编译一遍,源码的依赖才能完整。 2. 生成IDE导入的工程文件 执行完成后,在AOSP根目录下生成文件: 3. 导入前,编辑工程文件 (这步很重要,影响代码的加载速度和跳转) 编辑android.iml文件,需要修改2部

    2024年02月10日
    浏览(20)
  • Android 14 适配指南

    Android 14 适配指南

    Google2月按时发布了第一个开发者预览版本,正式版会在8-9月份发布。 按照惯例,Android更新了可以刷机的手机型号,Pixel 4仅支持4a(5G)版本: Pixel 4a (5G) Pixel 5 and 5a Pixel 6 and 6 Pro Pixel 6a Pixel 7 and 7 Pro 开发者可以参考Android官网(https://developer.android.com/about/versions/14/get)进行刷机

    2024年02月06日
    浏览(9)
  • Android14弹窗问题

    Android14弹窗问题

    升级安卓14后,应用没有适配对应的CPU架构而被系统强制弹窗,弹窗流程可见参考应用弹窗“此应用专为旧版Android打造,因此可能无法正常运行…”的原因,应用层面没办法去干扰这个流程,应该是在安装时有检测相关的包。 弹窗共有两个:此应用与最新版 Android 不兼容。请

    2024年02月04日
    浏览(8)
  • Android 14适配

    Android 14适配

    Google I/O 2023 发布的 Android beta2 ,Android 14 将在2023年第三季度发布。Google Play 已经开始强制要求targetSdkVersion 33适配,所以 targetSdkVersion 34适配也是非常有必要的。 前台服务类型(foregroundServiceType)是在 Android 10 引入的,通过 android:foregroundServiceType 可以指定 service 的服务类型,

    2024年02月16日
    浏览(9)
  • Android 14 媒体权限变化

    允许部分访问照片和视频 在Android 14设备上与您的应用程序交互的用户现在可以在应用程序请求Android 13(API级别33)中引入的任何视觉媒体权限(READ_media_IMAGES或READ_media-VIDEO)时授予对其视觉媒体库(照片/视频)的部分访问权限。 新对话框包含以下选项: 选择照片和视频:

    2024年02月05日
    浏览(16)
  • Android 14重要更新预览

    Android 14重要更新预览

    Android 14 在 Android 13 的基础上进一步扩展了按应用设定语言功能,提供了一些额外的功能: 自动生成应用的 localeConfig :从 Android Studio Giraffe Canary 7 和 AGP 8.1.0-alpha07 开始,您可以配置应用以自动支持各应用语言偏好设定。Android Gradle 插件将根据您的项目资源生成 LocaleConfig 文

    2024年02月14日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包