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(合成调度与策略决策) 决定每帧由 HWC 合成还是 GPU 合成,管理 VSYNC 与提交时序 HWC2 / HWC3 接口层 createDisplay / setLayerBuffer / validateDisplay / presentDisplay / getReleaseFences Composer HAL(HIDL / AIDL 稳定接口) 厂商实现:Display 热插拔、Layer 属性配置、合成能力上报 Display 对象 displayId / 分辨率 / 刷新率 物理连接类型 / 色彩空间 每个 Display 独立维护 Layer 列表 支持主屏、副屏、虚拟屏 Layer 对象 layerId / buffer / 裁剪区域 混合模式 / 变换矩阵 / Z 序 可见性 / 透明度 / 数据空间 由 SurfaceFlinger 创建并绑定到 Display 绑定

二、方法流程:一帧的合成决策路径

理解 HWC 架构最有效的方式是跟踪一帧的完整路径。SurfaceFlinger 在收到 VSYNC 后,会遍历所有活跃 Display,对每个 Display 执行以下流程:

  1. 收集 Layer:从该 Display 的 Layer 列表中获取所有可见 Layer,包括应用窗口、状态栏、壁纸等。
  2. 调用 validateDisplay:HWC 根据硬件能力判断哪些 Layer 可以由硬件直接合成(Device 合成),哪些必须回退到 GPU(Client 合成)。
  3. 处理合成结果:如果存在 Client 合成 Layer,SurfaceFlinger 会先将其渲染到 GPU 缓冲,再作为新的 Layer 提交给 HWC。
  4. 调用 presentDisplay:HWC 将最终合成结果提交到显示控制器,并返回 release fence。
  5. 释放缓冲: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 列表
复盘要点:多显示器集成中最容易出问题的地方是 Display 枚举顺序和 Layer 绑定关系。如果副屏的 Layer 被错误地绑定到主屏,会导致画面错位或黑屏。建议在 HAL 层增加 Display 状态日志,在 SurfaceFlinger 层增加 Layer 绑定日志,形成完整的链路追踪。