Android 15 View 绘制触发 BufferQueue / BLAST / SurfaceFlinger 上屏流程

Android 15 View 绘制触发 BufferQueue / BLAST / SurfaceFlinger 上屏流程 本文通过AI 基于 android-15.0.0_r17 整理并跟源码做了比对校准请参考。普通 View 硬件加速绘制时Java 层不会直接 Surface.lockCanvas()而是 ViewRootImpl 触发 ThreadedRendererRenderThread 通过 EGL/Skia/Vulkan/OpenGL 的 ANativeWindow 路径 dequeue buffer → GPU 绘制 → queue buffer。Android 15 应用窗口默认走 BLASTBufferQueueBuffer 被 BBQ 在 App 进程 acquire 后封装进 SurfaceControl.Transaction提交给 SurfaceFlinger。SurfaceFlinger 在事务/VSync 合成阶段 latch 该 buffer 并送显。Android 官方也明确描述 BufferQueue 的基本模型Producer dequeueBuffer() 获取 buffer填充后 queueBuffer()Consumer acquireBuffer() 后使用完成后 releaseBuffer()。BLAST 架构下BufferQueue 从 SurfaceFlinger 侧转移到业务进程buffer 和图层属性通过 Transaction 一起提交给 SurfaceFlinger。 [source.and…google.cn] [juejin.cn], [jianshu.com]1. 总体调用链1View.invalidate()/ requestLayout()2↓3ViewRootImpl.scheduleTraversals()4↓5Choreographer CALLBACK_TRAVERSAL等待下一帧 VSYNC6↓7ViewRootImpl.doTraversal()8↓9ViewRootImpl.performTraversals()10↓11performMeasure / performLayout / performDraw12↓13ViewRootImpl.draw()14↓15ThreadedRenderer.draw()16↓17updateRootDisplayList()// UIThread 构建 RenderNode / DisplayList18↓19syncAndDrawFrame()// 同步给 RenderThread20↓21RenderThread / HWUI / Skia22↓23ANativeWindow.dequeueBuffer()24↓25Surface::dequeueBuffer()26↓27BufferQueueProducer::dequeueBuffer()28↓29Gralloc 分配 / 复用 GraphicBuffer30↓31GPU 绘制到 GraphicBuffer32↓33eglSwapBuffers / queueBuffer34↓35Surface::queueBuffer()36↓37BufferQueueProducer::queueBuffer()38↓39BLASTBufferQueue::onFrameAvailable()40↓41BLASTBufferQueue acquire buffer42↓43SurfaceControl.Transaction.setBuffer()44↓45Transaction.apply()46↓47SurfaceFlinger 接收事务48↓49SurfaceFlinger latch buffer / compose50↓51HWC / Display 显示2. View 层invalidate / requestLayout 如何触发绘制2.1 View.invalidate()路径1 frameworks/base/core/java/android/view/View.java关键逻辑1 public void invalidate() {2 invalidate(true);3 }45 public void invalidate(boolean invalidateCache) {6 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop,7 invalidateCache, true);8 }910 void invalidateInternal(int l, int t, int r, int b,11 boolean invalidateCache, boolean fullInvalidate) {12 if (skipInvalidate()) {13 return;14 }1516 if ((mPrivateFlags PFLAG_DRAWN) PFLAG_DRAWN17 || (fullInvalidate isOpaque() ! mLastIsOpaque)) {1819 if (fullInvalidate) {20 mLastIsOpaque isOpaque();21 mPrivateFlags ~PFLAG_DRAWN;22 }2324 mPrivateFlags | PFLAG_DIRTY;2526 final AttachInfo ai mAttachInfo;27 final ViewParent p mParent;2829 if (p ! null ai ! null) {30 final Rect damage ai.mTmpInvalRect;31 damage.set(l, t, r, b);32 p.invalidateChild(this, damage);33 }34 }35 }这一步只是把 View 区域标记为 dirty并向父节点传播最终会到 ViewRootImpl.invalidateChildInParent()再触发 traversal。ViewRootImpl 是 View 树与窗口 / Surface 系统之间的桥梁负责 measure、layout、draw。 [juejin.cn], [jianshu.com]2.2 View.requestLayout()路径1 frameworks/base/core/java/android/view/View.java核心含义1 public void requestLayout() {2 if (mMeasureCache ! null) {3 mMeasureCache.clear();4 }56 if (mAttachInfo ! null mAttachInfo.mViewRequestingLayout null) {7 ViewRootImpl viewRoot getViewRootImpl();8 if (viewRoot ! null viewRoot.isInLayout()) {9 if (!viewRoot.requestLayoutDuringLayout(this)) {10 return;11 }12 }13 mAttachInfo.mViewRequestingLayout this;14 }1516 mPrivateFlags | PFLAG_FORCE_LAYOUT;17 mPrivateFlags | PFLAG_INVALIDATED;1819 if (mParent ! null !mParent.isLayoutRequested()) {20 mParent.requestLayout();21 }2223 if (mAttachInfo ! null mAttachInfo.mViewRequestingLayout this) {24 mAttachInfo.mViewRequestingLayout null;25 }26 }最终也会进入 ViewRootImpl.requestLayout()。3. ViewRootImpl调度下一帧 Traversal路径1 frameworks/base/core/java/android/view/ViewRootImpl.java3.1 requestLayout()1 Override2 public void requestLayout() {3 if (!mHandlingLayoutInLayoutRequest) {4 checkThread();5 mLayoutRequested true;6 scheduleTraversals();7 }8 }checkThread() 用来保证只有创建 ViewRootImpl 的线程能操作该 View 树这也是常见 “Only the original thread that created a view hierarchy can touch its views” 的来源。 [blog.csdn.net]3.2 scheduleTraversals()1 void scheduleTraversals() {2 if (!mTraversalScheduled) {3 mTraversalScheduled true;45 mTraversalBarrier 6 mHandler.getLooper().getQueue().postSyncBarrier();78 mChoreographer.postCallback(9 Choreographer.CALLBACK_TRAVERSAL,10 mTraversalRunnable,11 null);1213 notifyRendererOfFramePending();14 pokeDrawLockIfNeeded();15 }16 }这里做了几件关键事情1.设置 mTraversalScheduled true避免重复调度。2.往主线程 MessageQueue 插入同步屏障。3.向 Choreographer 注册 CALLBACK_TRAVERSAL。4.等下一次 VSYNC 到来后执行 traversal。Choreographer 驱动 ViewRootImpl 在 VSYNC 节奏下执行 measure/layout/draw相关机制在 Android 渲染分析资料中也有一致描述。 [blog.csdn.net], [zhuanlan.zhihu.com]3.3 TraversalRunnable1 final class TraversalRunnable implements Runnable {2 Override3 public void run() {4 doTraversal();5 }6 }3.4 doTraversal()1 void doTraversal() {2 if (mTraversalScheduled) {3 mTraversalScheduled false;45 mHandler.getLooper().getQueue()6 .removeSyncBarrier(mTraversalBarrier);78 performTraversals();9 }10 }4. ViewRootImpl.performTraversalsmeasure / layout / draw路径1 frameworks/base/core/java/android/view/ViewRootImpl.java核心结构可以抽象为1 private void performTraversals() {2 final View host mView;34 // 1. 与 WMS relayout获得 SurfaceControl / BLAST surface5 relayoutResult relayoutWindow(params, viewVisibility, insetsPending);67 // 2. 必要时 measure8 if (mLayoutRequested) {9 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);10 }1112 // 3. 必要时 layout13 if (didLayout) {14 performLayout(lp, mWidth, mHeight);15 }1617 // 4. draw18 if (!cancelDraw !newSurface) {19 performDraw();20 }21 }在 Android 15 应用窗口中relayoutWindow() 之后会通过 getOrCreateBLASTSurface() 创建 / 更新 BLASTBufferQueue Surface这一点在 Android 12 BLAST 机制分析中也有对应源码路径说明。 [jianshu.com], [juejin.cn]5. ViewRootImpl 创建 BLAST Surface路径1 frameworks/base/core/java/android/view/ViewRootImpl.java关键方法1 Surface getOrCreateBLASTSurface() {2 if (!mSurfaceControl.isValid()) {3 return null;4 }56 Surface ret null;78 if (mBlastBufferQueue null) {9 mBlastBufferQueue new BLASTBufferQueue(10 mTag,11 mSurfaceControl,12 mSurfaceSize.x,13 mSurfaceSize.y,14 mWindowAttributes.format);1516 ret mBlastBufferQueue.createSurface();17 } else {18 mBlastBufferQueue.update(19 mSurfaceControl,20 mSurfaceSize.x,21 mSurfaceSize.y,22 mWindowAttributes.format);23 }2425 return ret;26 }这一步的意义1 SurfaceControl // SurfaceFlinger 里的 Layer 句柄2 ↓3 BLASTBufferQueue // App 进程本地 BufferQueue4 ↓5 Surface // 给 HWUI / EGL / ANativeWindow 使用BLASTBufferQueue 把 BufferQueue 放在 App 进程侧SurfaceFlinger 不再直接作为该 BufferQueue 的 Consumer而是接收 App 通过 Transaction 提交的 buffer。 [juejin.cn], [jianshu.com]6. performDraw / draw进入硬件渲染路径1 frameworks/base/core/java/android/view/ViewRootImpl.java6.1 performDraw()1 private void performDraw() {2 boolean canUseAsync draw(fullRedrawNeeded);3 }6.2 draw()普通 View 默认硬件加速核心会走1 private boolean draw(boolean fullRedrawNeeded) {2 Surface surface mSurface;34 if (!surface.isValid()) {5 return false;6 }78 final ThreadedRenderer renderer mAttachInfo.mThreadedRenderer;910 if (renderer ! null renderer.isEnabled()) {11 renderer.draw(mView, mAttachInfo, this);12 } else {13 drawSoftware(surface, mAttachInfo, xOffset, yOffset,14 scalingRequired, dirty);15 }1617 return true;18 }注意硬件加速路径ThreadedRenderer.draw()不会调用 Java Surface.lockCanvas()。软件绘制路径drawSoftware() 会调用 mSurface.lockCanvas(dirty) 和 unlockCanvasAndPost()。软件绘制中 Surface.lockCanvas() / unlockCanvasAndPost() 的路径和 BufferQueue dequeue / queue 对应这在 Canvas 绘制源码分析中也有相同流程描述。 [cloud.tencent.com]7. ThreadedRendererUIThread 构建 DisplayListRenderThread 真正绘制 Buffer 路径1 frameworks/base/core/java/android/view/ThreadedRenderer.java关键结构1 void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {2 attachInfo.mIgnoreDirtyState true;34 final Choreographer choreographer attachInfo.mViewRootImpl.mChoreographer;5 choreographer.mFrameInfo.markDrawStart();67 updateRootDisplayList(view, callbacks);89 attachInfo.mIgnoreDirtyState false;1011 int syncResult syncAndDrawFrame(choreographer.mFrameInfo);12 }7.1 updateRootDisplayList()1 private void updateRootDisplayList(View view, DrawCallbacks callbacks) {2 updateViewTreeDisplayList(view);34 if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {5 RecordingCanvas canvas mRootNode.beginRecording(6 mSurfaceWidth, mSurfaceHeight);78 try {9 callbacks.onPreDraw(canvas);1011 canvas.drawRenderNode(view.updateDisplayListIfDirty());1213 callbacks.onPostDraw(canvas);14 } finally {15 mRootNode.endRecording();16 }17 }18 }这一步发生在 UIThread1 View.draw()2 ↓3 RenderNode / DisplayList 记录绘制命令并不直接把像素写进 buffer。7.2 syncAndDrawFrame()1 private int syncAndDrawFrame(FrameInfo frameInfo) {2 return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo,3 frameInfo.frameInfo.length);4 }JNI 后进入 native HWUI1 android_view_ThreadedRenderer_syncAndDrawFrame2 ↓3 RenderProxy::syncAndDrawFrame()4 ↓5 DrawFrameTask::drawFrame()6 ↓7 CanvasContext::draw()8 ↓9 SkiaOpenGLPipeline / SkiaVulkanPipeline10 ↓11 dequeue buffer12 ↓13 GPU render14 ↓15 queue buffer / swap buffersThreadedRenderer 的核心职责是UI 线程构建 DisplayListRenderThread 负责把 DisplayList 同步并渲染到 Surface 对应的 buffer。相关资料也指出硬件渲染分为 DisplayList 构建和 RenderThread 渲染两个阶段。 [blog.csdn.net]8. Surface / ANativeWindowdequeueBuffer 锁定可绘制 buffer路径1 frameworks/native/libs/gui/Surface.cpp8.1 ANativeWindow hook1 int Surface::hook_dequeueBuffer(2 ANativeWindow* window,3 ANativeWindowBuffer** buffer,4 int* fenceFd) {5 Surface* c getSelf(window);6 return c-dequeueBuffer(buffer, fenceFd);7 }89 int Surface::hook_queueBuffer(10 ANativeWindow* window,11 ANativeWindowBuffer* buffer,12 int fenceFd) {13 Surface* c getSelf(window);14 return c-queueBuffer(buffer, fenceFd);15 }EGL / Vulkan / HWUI 看到的是 ANativeWindow最终回调到 Surface::dequeueBuffer() 和 Surface::queueBuffer()。8.2 Surface::dequeueBuffer()核心逻辑1 int Surface::dequeueBuffer(2 ANativeWindowBuffer** buffer,3 int* fenceFd) {4 Mutex::Autolock lock(mMutex);56 int buf -1;7 sp fence;89 status_t result mGraphicBufferProducer-dequeueBuffer(10 buf,11 fence,12 reqWidth,13 reqHeight,14 reqFormat,15 reqUsage,16 mBufferAge,17 enableFrameTimestamps ? mFrameEventHistory : nullptr);1819 if (result 0) {20 return result;21 }2223 if ((result IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION)24 || gbuf nullptr) {25 result mGraphicBufferProducer-requestBuffer(buf, gbuf);26 if (result ! NO_ERROR) {27 mGraphicBufferProducer-cancelBuffer(buf, fence);28 return result;29 }30 }3132 if (fence ! nullptr fence-isValid()) {33 *fenceFd fence-dup();34 } else {35 *fenceFd -1;36 }3738 *buffer gbuf.get();39 return OK;40 }含义1 Surface2 调 IGraphicBufferProducer.dequeueBuffer()3 ↓4 BufferQueueProducer 找一个可用 slot5 ↓6 必要时分配 GraphicBuffer7 ↓8 返回 ANativeWindowBuffer 给 HWUI / EGL官方 BufferQueue 文档也描述了生产方通过 dequeueBuffer() 请求可用 buffer并指定宽高、格式和 usage。 [source.and…google.cn]9. BufferQueueProducer真正管理 buffer slot 状态路径1 frameworks/native/libs/gui/BufferQueueProducer.cpp9.1 dequeueBuffer()核心结构1 status_t BufferQueueProducer::dequeueBuffer(2 int* outSlot,3 spandroid::Fence* outFence,4 uint32_t width,5 uint32_t height,6 PixelFormat format,7 uint64_t usage,8 uint64_t* outBufferAge,9 FrameEventHistoryDelta* outTimestamps) {10 std::unique_lockstd::mutex lock(mCore-mMutex);1112 int found BufferQueueCore::INVALID_BUFFER_SLOT;1314 status_t status waitForFreeSlotThenRelock(15 FreeSlotCaller::Dequeue,16 found);1718 if (status ! NO_ERROR) {19 return status;20 }2122 *outSlot found;2324 mSlots[found].mBufferState.dequeue();2526 if (bufferNeedsReallocation) {27 returnFlags | BUFFER_NEEDS_REALLOCATION;28 }2930 return returnFlags;31 }buffer 状态变化1 FREE → DEQUEUEDBufferQueue 的常见状态流转是1 FREE → DEQUEUED → QUEUED → ACQUIRED → FREE该状态流转与 Android BufferQueue 工作流程资料一致。 [cnblogs.com], [zhuanlan.zhihu.com]9.2 queueBuffer()1 status_t BufferQueueProducer::queueBuffer(2 int slot,3 const QueueBufferInput input,4 QueueBufferOutput* output) {5 sp frameAvailableListener;6 BufferItem item;78 {9 std::unique_lockstd::mutex lock(mCore-mMutex);1011 mSlots[slot].mBufferState.queue();1213 item.mGraphicBuffer mSlots[slot].mGraphicBuffer;14 item.mFence acquireFence;15 item.mSlot slot;16 item.mFrameNumber currentFrameNumber;1718 mCore-mQueue.push_back(item);1920 frameAvailableListener mCore-mConsumerListener;21 }2223 if (frameAvailableListener ! nullptr) {24 frameAvailableListener-onFrameAvailable(item);25 }2627 return NO_ERROR;28 }buffer 状态变化1 DEQUEUED → QUEUED这一步就是“通知 buffer 可显示”的第一阶段Producer 已经把绘制完成的 buffer queue 进 BufferQueue并通知 Consumer。10. BLASTBufferQueueApp 进程本地消费 BufferQueue并通过 Transaction 交给 SurfaceFlinger路径1 frameworks/native/libs/gui/BLASTBufferQueue.cpp10.1 构造函数1 BLASTBufferQueue::BLASTBufferQueue(2 const std::string name,3 const sp surface,4 int width,5 int height,6 int32_t format)7 : mSurfaceControl(surface),8 mSize(width, height),9 mRequestedSize(mSize),10 mFormat(format) {1112 createBufferQueue(mProducer, mConsumer);1314 mProducer-setDequeueTimeout(15 std::numeric_limitsint64_t::max());1617 mProducer-setMaxDequeuedBufferCount(2);1819 mBufferItemConsumer new BLASTBufferItemConsumer(20 mConsumer,21 GraphicBuffer::USAGE_HW_COMPOSER |22 GraphicBuffer::USAGE_HW_TEXTURE,23 1,24 false);2526 mBufferItemConsumer-setFrameAvailableListener(this);27 mBufferItemConsumer-setBufferFreedListener(this);28 }这里创建1 BufferQueueProducer2 BufferQueueConsumer3 BLASTBufferItemConsumerAndroid 15 的 BLASTBufferQueue 分析资料也指出其构造中会 createBufferQueue(mProducer, mConsumer)设置 consumer listener并设置最大 dequeue buffer 数。 [jianshu.com], [blog.csdn.net]10.2 创建 Surface1 sp BLASTBufferQueue::createSurface() {2 return new BBQSurface(mProducer, true, this);3 }这个 Surface 最终给 ViewRootImpl.mSurface / HWUI 使用。10.3 onFrameAvailable()1 void BLASTBufferQueue::onFrameAvailable(2 const BufferItem item) {3 std::unique_lock lock(mMutex);45 mNumFrameAvailable;67 acquireNextBufferLocked(8 std::nullopt,9 std::nullopt,10 false /* dropBuffer */);11 }当 BufferQueueProducer::queueBuffer() 通知 frame available 后BLASTBufferQueue 作为本地 consumer 收到回调。10.4 acquireNextBufferLocked()核心逻辑1 status_t BLASTBufferQueue::acquireNextBufferLocked(2 const std::optionalSurfaceComposerClient::Transaction* transaction,3 const std::optionaluint64_t frameNumber,4 bool dropBuffer) {5 BufferItem bufferItem;67 status_t status mBufferItemConsumer-acquireBuffer(8 bufferItem,9 0 /* presentWhen/,10 false /waitForFence/);1112 if (status ! NO_ERROR) {13 return status;14 }1516 sp buffer bufferItem.mGraphicBuffer;17 sp fence bufferItem.mFence;1819 SurfaceComposerClient::Transaction localTransaction;20 SurfaceComposerClient::Transactiont 21 transaction ? *transaction : localTransaction;2223 t-setBuffer(mSurfaceControl, buffer, fence);24 t-setDataspace(mSurfaceControl, bufferItem.mDataSpace);25 t-setCrop(mSurfaceControl, bufferItem.mCrop);26 t-setTransform(mSurfaceControl, bufferItem.mTransform);2728 if (!transaction) {29 t-apply();30 }3132 return OK;33 }这一步非常关键1 BLASTBufferQueue 从本地 BufferQueue acquire buffer2 ↓3 把 GraphicBuffer acquire fence 塞进 SurfaceControl.Transaction4 ↓5 Transaction.apply()6 ↓7 通过 Binder 提交给 SurfaceFlinger所以在 Android 15 BLAST 路径下1 SurfaceFlinger 不直接 acquire App 窗口的 BufferQueue2 而是接收 Transaction 里的 buffer这一点是 Android S 以后 BLASTBufferQueue 的核心变化。 [juejin.cn], [jianshu.com]11. SurfaceFlinger接收事务、latch buffer、合成显示路径主要包括1 frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp2 frameworks/native/services/surfaceflinger/Layer.cpp3 frameworks/native/services/surfaceflinger/BufferStateLayer.cpp11.1 Transaction 到 SurfaceFlinger客户端1 SurfaceComposerClient::Transaction::apply()服务端大致进入1 status_t SurfaceFlinger::setTransactionState(2 const FrameTimelineInfo frameTimelineInfo,3 const Vector states,4 const Vector displays,5 uint32_t flags,6 const sp applyToken,7 const InputWindowCommands inputWindowCommands,8 int64_t desiredPresentTime,9 bool isAutoTimestamp,10 const client_cache_t uncacheBuffer,11 bool hasListenerCallbacks,12 const std::vector listenerCallbacks,13 uint64_t transactionId) {14 // 解析 Transaction15 // 放入 transaction queue16 // 请求下一帧 commit / composite17 }11.2 Layer 接收 buffer 状态BLAST 提交的 buffer 最终进入 Layer 的 buffer state例如1 bool BufferStateLayer::setBuffer(2 const sp buffer,3 const sp acquireFence,4 nsecs_t postTime,5 nsecs_t desiredPresentTime,6 bool isAutoTimestamp,7 const client_cache_t clientCacheId,8 uint64_t frameNumber,9 std::optionalnsecs_t dequeueTime,10 const FrameTimelineInfo info) {11 mDrawingState.buffer buffer;12 mDrawingState.acquireFence acquireFence;13 mDrawingState.frameNumber frameNumber;1415 return true;16 }含义1 SurfaceFlinger 的 Layer 状态里记录2 - GraphicBuffer3 - acquire fence4 - frame number5 - dataspace / crop / transform 等属性11.3 latch bufferSurfaceFlinger 在 commit / composition 阶段检查事务、处理 LayerState并把 pending buffer 变成当前可合成 buffer。抽象流程1 void SurfaceFlinger::commit() {2 // 处理 pending transaction3 // 更新 Layer state4 // latch buffer5 }67 void SurfaceFlinger::composite() {8 // 选择 GLES / HWC 合成方式9 // 等待 acquire fence10 // 提交给 Hardware Composer11 // present display12 }最终1 Layer buffer2 ↓3 SurfaceFlinger composition4 ↓5 HWC validate / present6 ↓7 Display 显示SurfaceFlinger 的职责是合成所有 Layer 并送显Android 显示系统资料中对此也有一致描述。 [juejin.cn], [jishuzhan.net]12. 软件绘制路径补充Surface.lockCanvas()如果关闭硬件加速或者某些特殊路径走软件绘制则 ViewRootImpl 会走1 private boolean drawSoftware(2 Surface surface,3 AttachInfo attachInfo,4 int xoff,5 int yoff,6 boolean scalingRequired,7 Rect dirty) {8 final Canvas canvas;910 try {11 canvas mSurface.lockCanvas(dirty);1213 canvas.setDensity(mDensity);1415 mView.draw(canvas);16 } finally {17 surface.unlockCanvasAndPost(canvas);18 }1920 return true;21 }对应 native1 Surface.lockCanvas()2 ↓3 Surface::lock()4 ↓5 Surface::dequeueBuffer()6 ↓7 GraphicBufferMapper::lock()8 ↓9 CPU 绘制 Canvas10 ↓11 Surface.unlockCanvasAndPost()12 ↓13 GraphicBufferMapper::unlock()14 ↓15 Surface::queueBuffer()也就是说路径 获取 buffer 绘制方式 提交方式硬件加速 View RenderThread / EGL dequeueBuffer GPU / Skia eglSwapBuffers / queueBuffer软件 View Surface.lockCanvas → dequeueBuffer CPU Canvas unlockCanvasAndPost → queueBuffer13. 三个关键行为对应源码位置13.1 “锁定 / 获取 buffer”硬件路径不是 Java lockCanvas()而是1 RenderThread2 ↓3 EGL / ANativeWindow4 ↓5 Surface::dequeueBuffer()6 ↓7 BufferQueueProducer::dequeueBuffer()关键源码1 mGraphicBufferProducer-dequeueBuffer(…);状态1 FREE → DEQUEUED13.2 “绘制 buffer”硬件路径1 ThreadedRenderer.updateRootDisplayList()2 ↓3 syncAndDrawFrame()4 ↓5 RenderThread6 ↓7 Skia / GLES / Vulkan8 ↓9 GPU 写入 GraphicBuffer软件路径1 Surface.lockCanvas()2 ↓3 View.draw(canvas)4 ↓5 CPU 写入 GraphicBuffer13.3 “通知 buffer 可显示”第一阶段1 BufferQueueProducer::queueBuffer()状态1 DEQUEUED → QUEUED并回调1 frameAvailableListener-onFrameAvailable(item);第二阶段BLAST1 BLASTBufferQueue::onFrameAvailable()2 ↓3 BLASTBufferQueue::acquireNextBufferLocked()4 ↓5 Transaction.setBuffer()6 ↓7 Transaction.apply()第三阶段SurfaceFlinger1 SurfaceFlinger 接收 Transaction2 ↓3 Layer latch buffer4 ↓5 Composition6 ↓7 HWC present14. Android 15 View 渲染流程时序图1 App UIThread RenderThread / HWUI BufferQueue / BBQ SurfaceFlinger2 | | | |3 | View.invalidate() | | |4 | requestLayout() | | |5 | ViewRootImpl.scheduleTraversals() | | |6 | Choreographer 等 VSYNC | | |7 | doTraversal() | | |8 | performTraversals() | | |9 | performMeasure/Layout | | |10 | performDraw() | | |11 | ThreadedRenderer.draw() | | |12 | updateRootDisplayList() | | |13 | syncAndDrawFrame() ---------------- | | |14 | | dequeueBuffer() ---------------- | BQP::dequeueBuffer() |15 | | | FREE → DEQUEUED |16 | | GPU render GraphicBuffer | |17 | | queueBuffer() ------------------- | BQP::queueBuffer() |18 | | | DEQUEUED → QUEUED |19 | | | onFrameAvailable() |20 | | | BBQ acquireBuffer() |21 | | | Transaction.setBuffer() ---- |22 | | | Transaction.apply() -------- |23 | | | | receive transaction24 | | | | latch buffer25 | | | | compose26 | | | | HWC present15. 校验结论我按 Android 15 的渲染架构对调用链做了交叉校验1.ViewRootImpl 调度链正确requestLayout() / invalidate() 最终触发 scheduleTraversals()通过 Choreographer 在 VSYNC 后执行 performTraversals()。 [juejin.cn], [blog.csdn.net]2.ThreadedRenderer 分工正确UIThread 构建 DisplayList / RenderNodeRenderThread 执行 syncAndDrawFrame() 并真实渲染 buffer。 [blog.csdn.net]3.BufferQueue 状态流转正确Producer dequeueBuffer()绘制后 queueBuffer()Consumer acquireBuffer()使用后 releaseBuffer()对应状态 FREE → DEQUEUED → QUEUED → ACQUIRED → FREE。 [source.and…google.cn], [cnblogs.com], [zhuanlan.zhihu.com]4.Android 15 BLAST 路径正确应用窗口的 BufferQueue 在 App 进程侧BLASTBufferQueue acquire buffer 后使用 SurfaceControl.Transaction.setBuffer() 提交给 SurfaceFlinger而不是 SurfaceFlinger 直接作为传统 BufferQueue consumer。 [juejin.cn], [jianshu.com]5.SurfaceFlinger 职责正确接收 Transaction更新 Layer buffer state在合成阶段 latch buffer并通过 HWC / GLES 合成送显。 [juejin.cn], [jishuzhan.net]16. 最终一句话总结Android 15 普通 View 的一次上屏本质是1 View 变化2 → ViewRootImpl 等 VSYNC 做 traversal3 → ThreadedRenderer 构建 DisplayList4 → RenderThread dequeue GraphicBuffer5 → GPU 绘制6 → queueBuffer7 → BLASTBufferQueue acquire buffer8 → Transaction 携带 buffer 提交给 SurfaceFlinger9 → SurfaceFlinger latch / compose / present其中1 锁定 buffer Surface / ANativeWindow dequeueBuffer2 绘制 buffer RenderThread Skia/GPU 写入 GraphicBuffer3 通知可显示 queueBuffer BLAST Transaction.apply4 最终显示 SurfaceFlinger latch HWC present-------------------------------------END LINE---------------------------------------------