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)送到"餐桌"(屏幕)。

相关推荐
洋不写bug1 小时前
JavaComparable、Comparator、Cloneable接口解析,深拷贝浅拷贝详细解析
android·java·开发语言
小孔龙2 小时前
Android 应用间 UI 刷新与合成
android
XiaoLeisj3 小时前
Kotlin Flow:冷流收集、并行订阅、emit 推送、delay 延迟、collect 全量收集与 collectLatest 的实时数据处理
android·kotlin·android jetpack·协程·flow
Android-Flutter4 小时前
android jetpack 详解
android·kotlin
三8444 小时前
文件上传基础
android
天空之城--5 小时前
Android Flutter行业最新动态与实用参考(2026年8月第2周)
android·flutter
三少爷的鞋5 小时前
预防远大于治理:Android 架构指南
android
恋猫de小郭5 小时前
Flutter 3.47 发布,快来看看有什么更新吧
android·前端·flutter