3. HWC 架构解析
在 Android 多显示器集成工程中,HWC(Hardware Composer)是 SurfaceFlinger 与显示硬件之间最关键的桥梁。它决定了每一帧由谁合成、在哪个显示设备上呈现、以什么时序提交。理解 HWC 的架构,核心是理解三层关系:上层接口(HWC2/HWC3)、中间抽象(Composer HAL)、底层对象模型(Display 与 Layer)。这三层共同构成了 Android 显示合成的“契约层”,也是多屏场景下问题最集中的地方。
一、核心原理:三层协作模型
SurfaceFlinger 并不直接操作显示控制器,而是通过 HWC 接口把“合成决策”委托给硬件。HWC2 是 Android 8.0 引入的接口版本,HWC3 则在其上增加了对多显示器、可变刷新率、更细粒度 Layer 能力的支持。Composer HAL 是 HIDL/AIDL 定义的稳定接口,负责把 HWC 的调用翻译成厂商实现。Display 与 Layer 则是运行时的对象模型:Display 代表一个物理或虚拟显示设备,Layer 代表一个可被合成的图形缓冲。
三者关系可以概括为:SurfaceFlinger 通过 HWC2/HWC3 接口调用 Composer HAL,Composer HAL 管理 Display 与 Layer 的生命周期和属性,最终由硬件完成合成或回退到 GPU 合成。多显示器场景下,每个 Display 独立维护自己的 Layer 列表和合成策略,这正是多屏差异化的根源。
二、方法流程:一帧的合成决策路径
理解 HWC 架构最有效的方式是跟踪一帧的完整路径。SurfaceFlinger 在收到 VSYNC 后,会遍历所有活跃 Display,对每个 Display 执行以下流程:
- 收集 Layer:从该 Display 的 Layer 列表中获取所有可见 Layer,包括应用窗口、状态栏、壁纸等。
- 调用 validateDisplay:HWC 根据硬件能力判断哪些 Layer 可以由硬件直接合成(Device 合成),哪些必须回退到 GPU(Client 合成)。
- 处理合成结果:如果存在 Client 合成 Layer,SurfaceFlinger 会先将其渲染到 GPU 缓冲,再作为新的 Layer 提交给 HWC。
- 调用 presentDisplay:HWC 将最终合成结果提交到显示控制器,并返回 release fence。
- 释放缓冲:SurfaceFlinger 根据 release fence 回收已使用的图形缓冲。
在多显示器场景下,上述流程会针对每个 Display 独立执行。这意味着主屏和副屏的合成策略可能完全不同:主屏可能全部由 HWC 硬件合成,而副屏由于硬件能力有限,可能大量回退到 GPU 合成,导致功耗和延迟差异。
三、案例场景:双屏异显的 Layer 分配
假设一个车载 Android 系统同时连接了中控主屏(1920×1080)和副驾娱乐屏(1280×720)。应用 A 在中控屏显示导航,应用 B 在副屏播放视频。此时 HWC 需要处理两个 Display 的 Layer 列表:
Display 0 (主屏, 1920x1080):
Layer 0: 导航地图 (Buffer, Device 合成)
Layer 1: 状态栏 (Buffer, Device 合成)
Layer 2: 悬浮窗 (Buffer, Client 合成 → GPU 预合成)
Display 1 (副屏, 1280x720):
Layer 0: 视频播放 (Buffer, Device 合成)
Layer 1: 控制栏 (Buffer, Device 合成)
Layer 2: 通知提示 (Buffer, Client 合成 → GPU 预合成)
如果副屏的 HWC 实现不支持多层叠加,validateDisplay 会返回大量 Client 合成 Layer,SurfaceFlinger 需要额外进行一次 GPU 合成。此时可以通过 dumpsys SurfaceFlinger 查看每个 Display 的合成统计,确认是否存在过度回退。
adb shell dumpsys SurfaceFlinger --display-id 可以列出所有 Display 的 ID 和状态;使用 adb shell dumpsys SurfaceFlinger --list 可以查看当前所有 Layer 及其所属 Display。多屏问题排查时,先确认 Display 是否被正确枚举,再检查 Layer 是否绑定到了正确的 Display。
四、误区与复盘:常见架构理解偏差
在实际工程中,开发者常对 HWC 架构存在以下误解:
| 误区 | 正确理解 |
|---|---|
| HWC 负责所有合成 | HWC 只负责硬件合成部分,Client 合成仍由 SurfaceFlinger 通过 GPU 完成 |
| 一个 Layer 只能属于一个 Display | Layer 在创建时绑定到 Display,但可以通过 reparent 操作迁移到其他 Display |
| HWC2 和 HWC3 只是版本号差异 | HWC3 增加了多显示器能力查询、可变刷新率、更细粒度的 Layer 属性支持 |
| Composer HAL 是 Android 框架的一部分 | Composer HAL 是厂商实现的稳定接口,Android 只定义接口规范,不提供具体实现 |
| Display 热插拔由 SurfaceFlinger 直接处理 | 热插拔事件由 Composer HAL 上报,SurfaceFlinger 通过 HWC 接口感知并更新 Display 列表 |