Android随笔-SurfaceFlinger

SurfaceFlinger 是 Android 图形系统的核心合成引擎,运行在 Native 层的独立进程(surfaceflinger)中,负责将来自不同应用和系统组件的图形缓冲区(Buffer)合成一帧,最终输出到屏幕显示。

一、SurfaceFlinger 的定位

如果把 Android 显示系统比作一个电影后期制作团队:

角色 对应组件 职责
导演/编剧 App(Framework 层) 决定画面内容,生成画面素材
素材库 BufferQueue 存放待合成的帧缓冲区
后期合成师 SurfaceFlinger 把多个素材合成为最终画面
放映机 Display / HWC 把最终画面送到屏幕

SurfaceFlinger 本身不生产内容,它只负责收集、合成、输出

二、在 Android 图形架构中的位置

复制代码
┌─────────────────────────────────────────────────────┐
│                   App 层 (Java/Kotlin)               │
│              View.draw() → Canvas → Surface          │
├─────────────────────────────────────────────────────┤
│              Framework 层 (Java)                     │
│         Surface / SurfaceControl / SurfaceSession   │
├─────────────────────────────────────────────────────┤
│              Native 层 (C++)                         │
│    ┌──────────────┐    ┌─────────────────────┐      │
│    │  BufferQueue │ ←→ │    SurfaceFlinger   │      │
│    │  (缓冲队列)   │    │   (合成引擎)         │      │
│    └──────────────┘    └─────────────────────┘      │
│              ↑                       ↓              │
│    ┌──────────────┐    ┌─────────────────────┐      │
│    │   Gralloc    │    │    HWComposer (HWC) │      │
│    │ (内存分配)   │    │   (硬件合成器)       │      │
│    └──────────────┘    └─────────────────────┘      │
│              ↑                       ↓              │
│    ┌──────────────┐    ┌─────────────────────┐      │
│    │   内核/驱动   │    │    Display 屏幕     │      │
│    │  (DRM/ION)   │    │                     │      │
│    └──────────────┘    └─────────────────────┘      │
└─────────────────────────────────────────────────────┘

三、核心概念:Surface、Layer、BufferQueue

1. Surface(表面)

  • 一个 Surface 对应一块可绘制的内存区域
  • App 的每个 Window(包括 Activity、Dialog、SurfaceView)都对应一个 Surface
  • App 通过 Canvas 或 OpenGL ES 在 Surface 上绘制内容

2. BufferQueue(缓冲队列)

  • 由 BufferQueueProducer(生产者,App 端)和 BufferQueueConsumer(消费者,SurfaceFlinger 端)组成
  • 采用生产者-消费者模型,解耦了"绘制"和"合成"两个环节
  • 默认使用 Triple Buffer(三重缓冲):减少 GPU 绘制与 SurfaceFlinger 合成之间的等待,提升流畅度

3. Layer(图层)

  • SurfaceFlinger 内部用 Layer 对象封装一个 Surface
  • 每个 Layer 包含:
    • 一个 BufferQueue(获取最新一帧内容)
    • 位置、大小、透明度、变换矩阵等元数据
    • Z-order(层级,决定谁在上谁在下)

四、SurfaceFlinger 的工作流程

步骤 1:接收 VSync 信号

  • 屏幕以固定频率刷新(60Hz/90Hz/120Hz)
  • SurfaceFlinger 通过 HWComposer 接收硬件 VSync 信号
  • 收到信号后,触发一帧的合成工作

步骤 2:收集所有 Layer

  • SurfaceFlinger 遍历当前所有可见的 Layer
  • 从每个 Layer 的 BufferQueue 中获取最新的一帧(dequeueBuffer)
  • 如果某个 Layer 没有新内容,则复用上一帧

步骤 3:合成(Composition)

合成有两种方式,SurfaceFlinger 会智能选择:

合成方式 执行者 原理 性能
GPU 合成 GPU 将多个 Layer 作为纹理,通过 OpenGL ES / Vulkan 渲染到 FrameBuffer 耗电高,通用性强
HWC 合成 显示芯片(DPU) 硬件直接将多个 Layer 叠加输出,绕过 GPU 省电高效,但受硬件能力限制

HWComposer(HWC) 是 HAL 层模块,由芯片厂商(高通、联发科等)实现。它会告诉 SurfaceFlinger:"这 3 个 Layer 我能硬件合成,剩下 2 个你交给 GPU"。

步骤 4:输出到屏幕

  • 合成后的最终帧通过 DRM/KMS(Linux 显示驱动)或厂商私有驱动送到屏幕
  • 屏幕在下一个 VSync 周期显示这帧画面

五、关键机制详解

1. Triple Buffer(三重缓冲)

复制代码
┌─────────┐   ┌─────────┐   ┌─────────┐
│ Buffer 0│   │ Buffer 1│   │ Buffer 2│
│  显示中  │   │  GPU绘制 │   │  空闲   │
└─────────┘   └─────────┘   └─────────┘
  • Buffer 0:正在被屏幕显示
  • Buffer 1:GPU 正在绘制下一帧
  • Buffer 2:空闲缓冲,App 可以立即开始画下下帧
  • 作用:消除 GPU 绘制与屏幕刷新之间的等待,避免卡顿(Jank)

2. VSync 与 Choreographer

  • VSync(垂直同步):屏幕硬件发出的刷新信号
  • Choreographer :Framework 层的"编舞师",接收 VSync 后统一调度:
    1. 输入事件处理
    2. 动画更新
    3. View 测量/布局/绘制
    4. 提交 Buffer 到 SurfaceFlinger
  • 如果 App 绘制超时(超过一个 VSync 周期),就会掉帧

3. SurfaceControl 与 Transaction

  • Android 10+ 引入 SurfaceControl 和 Transaction 机制
  • 允许批量修改 Layer 属性(位置、大小、透明度),原子性提交
  • 是实现流畅窗口动画(如分屏、PIP 画中画)的基础

六、SurfaceFlinger 与 Framework 的关系

Framework 调用 对应 SurfaceFlinger 操作
WindowManager.addView() 创建新的 Surface/Layer
View.invalidate()draw() 将内容绘制到 Surface 的 Buffer
Surface.unlockCanvasAndPost() 将 Buffer 提交到 BufferQueue,通知 SurfaceFlinger
Choreographer.doFrame() 触发整帧绘制,最终通过 Binder 调用 SurfaceFlinger
Activity.onResume() 窗口切换 SurfaceFlinger 调整 Layer Z-order

七、常见问题

问题 答案要点
为什么 SurfaceView 比 TextureView 更流畅? SurfaceView 有独立 Surface,直接通过 SurfaceFlinger 合成,不经过 View 系统的重绘;TextureView 作为普通 View 的一部分,需参与 View 树的绘制和合成
掉帧(Jank)是怎么产生的? App 绘制耗时超过 VSync 周期,或 SurfaceFlinger 合成耗时过长,导致错过屏幕刷新时机
HWC 和 GPU 合成的区别? HWC 由显示芯片硬件完成,省电且性能高,但受硬件 Layer 数量限制;GPU 合成灵活但耗电
为什么 Android 用 Triple Buffer 而不是 Double Buffer? Triple Buffer 在 GPU 绘制和屏幕显示之间增加了一个缓冲,允许 App 提前开始下一帧绘制,减少等待

八、总结

SurfaceFlinger 是 Android 显示系统的"中央厨房":各 App 把做好的"菜"(Buffer)放到窗口(Layer)里,SurfaceFlinger 按顺序(Z-order)把这些菜摆盘合成,通过"传菜员"(HWC/GPU)送到"餐桌"(屏幕)。

相关推荐
千里马学框架15 小时前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台15 小时前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone15 小时前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc16 小时前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo17 小时前
Kotlin 协程中的 Job 结构化并发与取消
android
sun00770018 小时前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼18 小时前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone19 小时前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen19 小时前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone19 小时前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui