View绘制上屏流程

App显示在屏幕上完整流程:

android12开始,producer,consumer,BufferQueue以及Buffer的dequeue,queue,acquire,release都从SurfaceFlinger移到了App端实现,如下图

View上屏流程:

  • view.invalidate/requestlayout发出绘制请求
  • vsync会触发绘制请求任务(uithread调用syncframestate把界面元素传递给RenderThread生成displaylist)
  • RenderThread调用opengl接口把displaylist绘制成像素放到graphicbuffer,然后再调用queuebuffer放到App的bufferqueue(release fence)

App queueBuffer→ frameAvailableListener.onFrameAvailable→BufferQueueConsumer::processNextBufferLocked

binder通知SurfaceFlinger.BufferQueueConsumer::acquireBuffer 获取一个graphicbuffer调用SurfaceComposerClient::Transaction.setBuffer保存到surfaceflinger layer中,并向hwc发送vsync请求

  • SurfaceFlinger在下一个vsync到来后询问hwc每个layer是否需要gpu合成
  1. gpu合成:renderengine模块把所有window的bufferqueue调用aquirebuffer拿到要合成buffer,调用gpu合成之后放到framebuffer,hwc再根据framebuffer合成1个layer走device合成过程,并释放fence( gpu合成原理是通过拿到可用buffer合成帧数据放到framebufferlayers合成_surfaceflinger 合成是通过hwc还是gpu-CSDN博客
  2. device合成:layer直接透传到hwc,透传给display,display从每个layer的bufferqueue中读取像素显示到屏幕

SurfaceFlinger消费bufferqueque

onVsync -> SurfaceFlinger::onMessageInvalidate() -> BufferLayer::latchBuffer() -> BufferQueueLayer::updateTexImage() 

{

    BufferLayerConsumer::acquireBufferLocked() 
   BufferLayerConsumer::updateAndReleaseLocked

}

  • Surfaceflinger RenderEngine负责把每个texture合成生成framebuffer之后交给hwc消费

SkiaGLRenderEngine.cpp文件在native/libs/renderengine 目录下
drawlayers方法负责将所有layers的buffer描画到屏幕的framebuffer中,drawlayers方法在描画中,会根据layerSettings的具体信息为各个layer添加某些显示特效(例如圆角窗口,窗口阴影,高斯模糊效果)

多个App在屏幕上显示流程:

1个App Window从SurfaceFlinger申请1个surface时,会创建1个window对应的BufferQueue,每个BufferQueue包含3个buffer(SF合成图像也是在Gpu完成的)

关键流程

一,App完成1帧数据时把生产的buffer通过binder传给SurfaceFlinger去消费

 queueBuffer→frameAvailableListener.onFrameAvailable

→BufferQueueConsumer::processNextBufferLocked→BufferQueueConsumer::acquireBuffer

(像app要buffer来消费)

→BLASTBufferQueue#SurfaceComposerClient::Transaction.setBuffer(mSurfaceControl, buffer, releaseCallbackId, releaseBufferCallback)

二,SurfaceFlinger消费完之后releasebuffer

Surfaceflinger E TransactionCallbackInvoker: TransactionCallbackInvoker ITransactionCompletedListener onTransactionCompleted
Surfaceflinger E ITransactionCompletedListener:onTransact BpTransactionCompletedListener onTransactionCompleted
Client ITransactionCompletedListener: -----------------------onTransact BnTransactionCompletedListener onTransactionCompleted
Client BLASTBufferQueue: releaseBufferCallbackThunk→ProducerListener.onBufferReleased()
Client BufferQueueConsumer: [SurfaceView[com.jidu.rearscreen/com.jidu.rearscreen.MainActivity]#1(BLAST Consumer)1]
Client releaseBuffer: releasing slot 0

调用stack如下

BufferQueueConsumer: stackdump:#00 pc 000580ff  /system/lib/libgui.so (android::BufferQueueConsumer::releaseBuffer(int, unsigned long long, android::sp<android::Fence> const&, void*, void*)+130)
BufferQueueConsumer: stackdump:#01 pc 00059117  /system/lib/libgui.so (android::BufferQueueConsumer::releaseBuffer(int, unsigned long long, void*, void*, android::sp<android::Fence> const&)+30)
BufferQueueConsumer: stackdump:#02 pc 00076d27  /system/lib/libgui.so (android::ConsumerBase::releaseBufferLocked(int, android::sp<android::GraphicBuffer>, void*, void*)+134)
BufferQueueConsumer: stackdump:#03 pc 0007580d  /system/lib/libgui.so (android::BufferItemConsumer::releaseBuffer(android::BufferItem const&, android::sp<android::Fence> const&)+140)
BufferQueueConsumer: stackdump:#04 pc 0006c467  /system/lib/libgui.so (android::BLASTBufferQueue::releaseBufferCallback(android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int)+1362)
BufferQueueConsumer: stackdump:#05 pc 0006d827  /system/lib/libgui.so (android::releaseBufferCallbackThunk(android::wp<android::BLASTBufferQueue>, android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int)+62)
BufferQueueConsumer: stackdump:#06 pc 0007039b  /system/lib/libgui.so (std::__1::__function::__func<std::__1::__bind<void (&)(android::wp<android::BLASTBufferQueue>, android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int), android::wp<android::BLASTBufferQueue>, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&, std::__1::placeholders::__ph<4> const&>, std::__1::allocator<std::__1::__bind<void (&)(android::wp<android::BLASTBufferQueue>, android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int), android::wp<android::BLASTBufferQueue>, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&, std::__1::placeholders::__ph<4> const&> >, void (android::ReleaseCallbackId const&, android::sp<android::Fence> const&, unsigned int, unsigned int)>::operator()(android::ReleaseCallbackId const&, android::sp<android::Fence> const&,
BufferQueueConsumer: stackdump:#07 pc 000a7d47  /system/lib/libgui.so (android::TransactionCompletedListener::onTransactionCompleted(android::ListenerStats)+3382)
BufferQueueConsumer: stackdump:#08 pc 000925a5  /system/lib/libgui.so (int android::SafeBnInterface<android::ITransactionCompletedListener>::callLocalAsync<void (android::ITransactionCompletedListener::*)(android::ListenerStats)>(android::Parcel const&, android::Parcel*, void (android::ITransactionCompletedListener::*)(android::ListenerStats))+204)
BufferQueueConsumer: stackdump:#09 pc 00028ddb  /system/lib/libbinder.so (android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+162)
12-15 10:46:54.793667  2959  3319 E BufferQueueProducer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) queueBuffer: slot=0/19261 time=652049692092 dataSpace=0 validHdrMetadataTypes=0x0 crop=[0,0,0,0] transform=0 scale=SCALE_TO_WINDOW
12-15 10:46:54.793705  2959  3319 E BufferQueueConsumer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) acquireBuffer: acquiring { slot=0/19261 buffer=0x74f1a1b440 } notify_all  queuesize:1

12-15 10:46:54.802876  2959  3319 E BufferQueueProducer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) dequeueBuffer

12-15 10:46:54.742224  2959  3028 E BufferQueueConsumer: [SurfaceView[com.jidu.renderframe/com.jidu.renderframe.MainActivity]#1(BLAST Consumer)1](id:b8f00000001,api:1,p:2959,c:2959) releaseBuffer: releasing slot 2 DequeueCondition.notify_all
源码如下:
    void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
                         uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override {
                         
        callRemoteAsync<decltype(
                &ITransactionCompletedListener::onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER,
                                                                  callbackId, releaseFence,
                                                                  transformHint,
                                                                currentMaxAcquiredBufferCount);
}

releaseBuffer流程:

BufferStateLayer::~BufferStateLayer onReleaseBuffer
12-25 21:00:18.606   603   603 E ITransactionCompletedListener: -----------------------onTransact BpTransactionCompletedListener onTransactionCompleted
12-25 21:00:18.606 12674 14754 E ITransactionCompletedListener: -----------------------onTransact BnTransactionCompletedListener onTransactionCompleted
12-25 21:00:18.606 12674 14754 E BLASTBufferQueue: releaseBufferCallbackThunk    BufferQueueConsumer:releaseBuffer: releasing slot x

Systrace全流程:

  1. App绘制到dequeue到buffer
  2. Consumer aquirebuffer之后把buffer设置给Surfaceflinger
  3. Surfaceflinger 消费完了 releaseBuffer

关键概念:

  • sf合成layer方式:优先硬件合成,合成失败才用gpu合成兜底

1种:hwc(高通开发的屏幕芯片dpu做)硬件合成,但是不能合成alpha,高斯模糊这种复杂图像

1种:soft (client/gpu)不会出错, cpu占用高

  • SurfaceFlinger的线程:acquire,queue,dequeue采用主线程,releaseBuffer采用子线程
  • BBQ(BufferQueue的增强类BlastBufferQueue)【BufferQueue中是BufferSlot来保存Buffer状态,1个Buffer有四种状态: Dequeued, Queued, Acquired, Free】
  • QueuedBuffer - X                  生产者队列,sf会从这个队列中获取buffer
  • BLAST Consumer - X           消费者队列
  • SurfaceFlinger为每个surface创建的BufferStateLayer,封装在mSurfaceControl暴露给客户端,mSurfaceControl中新建了BLASTBufferQueue
  • BLASTBufferQueue分别又创建BufferQueueCore,BufferQueueProducerBufferQueueConsumer持有相同的BufferQueueCore:
  • BufferQueueCore是graphicbuffer存储的数据结构,包含如下2个变量:

    mSlots:包含了默认大小为64的BufferSlot数组,但一个surface默认初始化3个buffrer,

    mQueue :BufferItem类型的数组,生产者和消费者按照Fifo规则消费queque中的数据

    Producer调用queueBuffer后会修改mSlots,mQueue(但不知道这2个的区别在哪里)

    BufferSlot是1个graphicbuffer封装,成员变量有mGraphicBuffer,mBufferState(buffer的状态是free,queued,aquired,dequeue), mFence(前主人是否用完的标志),SurfaceTexture可以对Graphic Buffers做自定义特效处理

  • 将图形内存Graphic Buffer送到LCD显示的2种方法:gpu合成gralloc.post()和hwcomposer的硬件合成
  • 从view.invalide()提交绘制请求到display显示至少隔3帧(一个surface和SurfaceFlinger有3个buffer轮流使用)
  • dequeueBuffer阻塞之后有timeout(默认是4s) W OpenGLRenderer: dequeueBuffer failed, error = -110; switching to fallback
  • 关于dequeueBuffer等buffer相关bug,搜索:SurfaceFlinger,dequeueBuffer关键字
  • fence机制:fence对象通过fd在3个进程之间共享
  • 释放fence时机:App在gpu绘制一帧完毕,SurfaceFlinger在updateTexImage,HWC在合成完毕(HWC合成开始前提是gpu和device合成用到的fence都可用)
  • 错误汇总
  • 04-20 15:05:56.217276   597   597 E SurfaceFlinger: Attempted to create an ExternalTexture for layer lrc#0 that exceeds render target size limit.
  • 12-14 15:55:53.495030   583   583 E BpTransactionCompletedListener: Failed to transact (-2147483646)   surfaceflinger通知释放buffer失败了
  • RenderThread: BufferQueueProducer: setDequeueTimeout:4000(

    但注意!UnityMain  Thread:一直阻塞不会Timeout,BufferQueueProducer: [SurfaceView[com.cottongame.triangleAdventure.jidu/com.unity3d.player.MainActivity]#1(BLAST Consumer)1]

  • trace分析卡顿,Davey! duration主线程卡顿

debuyg测试surfaceflinger方法

编译:make surfaceflinger

替换车机中的文件:将out/target/product/msmnile_gvmq/system/bin/surfaceflinger 文件

替换车机中的system/bin/surfaceflinger文件

重启Android系统:adb shell reboot

参考文献

aosp源码路径 Android/lagvm/LINUX/android/frameworks/native/libs/gui#

native/services/surfaceflinger/

android app渲染流水线图解

surface  Android 图形系统之 SurfaceTexture

Android 图形图像 - 随笔分类 - 二的次方 - 博客园

<think>嗯,用户提到了几个错误日志,我需要先理解每个错误的具体含义和可能的原因。首先,用户给出的错误信息主要涉及Android系统层的几个问题,包括Parcel、Surface和libVT库相关的错误。 第一个错误是“E Parcel: dup() failed in Parcel::read”,提示dup()函数调用失败,原因是“Too many open files”。这通常意味着进程打开了太多的文件描述符,超过了系统的限制。这时候需要检查是否有文件或资源泄漏,特别是在频繁操作文件、数据库或网络连接时没有正确关闭。接下来,用户还提到了i=0,fds[i]=-1,fd_count=1,这可能是在反序列化文件描述符时遇到了无效的fd,导致无法复制。 然后是“E Surface: dequeueBuffer failed”,错误码-22(Invalid argument)。这可能与GraphicBuffer的分配或配置有关。常见的原因包括Surface的尺寸或格式不正确,或者BufferQueue出现了状态不一致的问题。此外,如果Surface已经被释放但仍被访问,也会导致此类错误。 接下来是libVT库的错误,ANativeWindow_lock失败,同样返回-22。这可能是因为传递给ANativeWindow_lock的参数无效,或者底层的Surface已经失效。此外,线程管道问题(QEventDispatcherUNIXPrivate错误)可能涉及线程间通信的管道无法创建,可能由于资源耗尽或权限问题。 综合来看,这些错误可能相互关联。例如,文件描述符泄漏导致系统资源耗尽,进而影响Surface和ANativeWindow的操作,最终导致图形缓冲区无法正确分配,引发后续错误。或者,Surface配置错误导致ANativeWindow操作失败,同时资源泄漏加剧了问题。 可能的解决步骤包括:首先检查文件描述符泄漏,使用lsof或/proc/<pid>/fd进行排查;然后检查Surface的使用,确保配置正确,及时释放和重新创建;接着验证libVT库的使用是否符合ANativeWindow的要求;最后处理线程管道问题,可能需要检查线程管理和资源限制。 需要提醒用户注意代码中的资源管理,尤其是在多线程或频繁操作硬件的情况下,确保正确释放资源。同时,建议使用工具如StrictMode或内存分析工具来辅助检测泄漏和资源问题。</think>这些错误日志涉及Android底层系统资源管理、图形缓冲区分配和线程通信的问题。以下是逐步分析及解决方案: --- ### **1. `E Parcel: dup() failed` 错误分析** - **错误原因**:`dup()`系统调用失败,提示`Too many open files`。 - **关键点**: - 进程的文件描述符(File Descriptor)数量超过系统限制。 - 常见于未正确关闭文件、Socket、数据库连接或`ParcelFileDescriptor`。 - **解决方案**: 1. **检查文件泄漏**: - 使用`adb shell lsof -p <PID>`查看进程打开的文件。 - 检查代码中是否有未关闭的`Cursor`、`InputStream`或`ParcelFileDescriptor`。 2. **调整系统限制**: - 临时方案:`ulimit -n 1024`(需root权限)。 - 永久方案:修改`/etc/security/limits.conf`。 --- ### **2. `E Surface: dequeueBuffer failed` 错误分析** - **错误原因**:`IGraphicBufferProducer::requestBuffer`返回错误`-22`(`Invalid argument`)。 - **关键点**: - `Surface`的缓冲区队列(BufferQueue)状态异常。 - 常见于`SurfaceTexture`释放后仍被访问,或缓冲区尺寸/格式不兼容。 - **解决方案**: 1. **检查Surface生命周期**: - 确保`Surface`未被提前释放(如`Surface.release()`后仍调用`dequeueBuffer`)。 2. **验证缓冲区参数**: - 检查`setBufferSize()`或`setFormat()`的参数是否合法。 3. **重试机制**: - 捕获异常后重新创建`Surface`(需业务逻辑支持)。 --- ### **3. `libVT-800CE_armeabi-v7a.so` 相关错误分析** - **错误原因**: - `ANativeWindow_lock()`失败(错误码`-22`),提示底层图形接口异常。 - `QEventDispatcherUNIXPrivate`线程管道创建失败。 - **关键点**: - 可能由`ANativeWindow`关联的`Surface`失效或参数错误导致。 - 线程间通信管道因资源耗尽(FD或内存)无法创建。 - **解决方案**: 1. **检查ANativeWindow绑定**: - 确保`ANativeWindow`与有效的`Surface`关联,且未被释放。 2. **验证图形参数**: - 检查`ANativeWindow_lock()`的`width`、`height`、`format`是否合法。 3. **排查线程资源**: - 检查线程是否泄漏(如未正确退出)。 - 使用`pthread`调试工具(如`strace`)跟踪线程行为。 --- ### **4. 综合问题关联性** - **资源泄漏连锁反应**: - 文件描述符泄漏(`E Parcel`)→ 系统资源耗尽 → 图形缓冲区分配失败(`E Surface`)→ 底层库崩溃(`libVT`)。 - **硬件加速问题**: - 视频编解码库(如`libVT`)可能依赖硬件加速,需检查`MediaCodec`配置或驱动兼容性。 --- ### **建议排查步骤** 1. **监控系统资源**: - 使用`adb shell dumpsys meminfo <package>`检查内存泄漏。 - 通过`adb shell cat /proc/<PID>/limits`查看FD限制。 2. **简化复现路径**: - 在最小化代码中复现问题(如仅保留图形渲染逻辑)。 3. **更新依赖库**: - 检查`libVT`库是否为最新版本,或联系供应商提供兼容性修复。 --- ### **示例代码修复(伪代码)** ```java // 正确释放Surface示例 try { Surface surface = holder.getSurface(); // 使用surface进行渲染... } finally { if (surface != null) { surface.release(); // 确保释放 } } // 检查ANativeWindow合法性 if (ANativeWindow_isValid(nativeWindow)) { ANativeWindow_lock(nativeWindow, ...); } else { // 重新创建nativeWindow } ``` 通过以上步骤,可系统性定位资源泄漏、图形接口失效或线程通信异常的根本原因。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值