1. 课程导入

欢迎进入《Android HWC多显示器集成工程》。在车载座舱、折叠屏、AR/VR、桌面模式以及工业控制终端中,一块 SoC 同时驱动两三块甚至更多屏幕,已经从“加分项”变成“基本盘”。但很多工程师第一次接触多显示器时,会把它简单理解为“多接一根线、多开一个 Surface”,真正动手后才发现:显示链路、合成策略、热插拔时序、带宽分配、HWC 与 SurfaceFlinger 的职责边界,任何一环没打通,副屏就是黑屏、花屏、掉帧或延迟。本课程的目标,就是把这套链路从概念到代码、从配置到排障完整讲透。

一、学习目标:从“能亮”到“可控、可测、可量产”

本课程不是 API 手册的复述,而是围绕工程交付展开。学完之后,你应当具备四项能力:第一,能画出从应用层到显示控制器(Display Controller)的完整数据通路,说清每一层在多显示器场景下多出了什么;第二,能读懂并修改 HWC 的显示配置、图层合成与热插拔处理逻辑;第三,能针对镜像、扩展、独立三种显示模式设计合成策略并评估性能;第四,能使用 dumpsys、HWC 日志、trace 等工具定位黑屏、撕裂、掉帧、延迟等典型问题。

核心判断标准:多显示器集成是否成功,不看“能不能显示”,而看“切换是否稳定、帧率是否达标、延迟是否可接受、异常是否可恢复”。

二、核心概念:先建立正确的对象模型

多显示器集成的第一道门槛是术语。Android 显示体系中,Physical Display 是真实存在的物理屏,由 HWC 枚举并管理;Logical Display 是 DisplayManagerService 面向应用暴露的逻辑显示单元,通常与物理屏一一对应,但在镜像或虚拟显示场景下可以多对一或一对多;DisplayDevice 是 SurfaceFlinger 内部的显示设备抽象,承载合成目标;Layer 是需要被合成的图层,最终由 HWC 决定“谁叠加、谁送 GPU、谁直接扫描输出”。

HWC(Hardware Composer)是本节最核心的对象。它位于 SurfaceFlinger 与显示驱动之间,职责是接收图层列表和显示配置,返回合成决策:哪些图层由硬件叠加器(Overlay)直接合成,哪些必须回退到 GPU(Client Composition)。多显示器场景下,HWC 还要处理每个显示设备独立的图层栈、独立的刷新率、独立的色彩空间以及热插拔事件。

  • DisplayManagerService:显示设备的注册、状态维护与逻辑显示映射。
  • SurfaceFlinger:图层管理、合成调度、与 HWC 交互。
  • HWC HAL:厂商实现的硬件合成抽象层,负责能力上报与合成决策。
  • DRM/KMS 或厂商显示驱动:真正操作 CRTC、Plane、Encoder、Connector 的底层。

三、整体框架:一张图看清多显示器数据流

下面的 SVG 展示了从应用到物理屏的完整链路,以及多显示器场景下新增的关键分支。请重点观察:每个物理屏在 HWC 层拥有独立的 Display 上下文,SurfaceFlinger 需要为每个显示设备分别准备合成输入,而 GPU 合成与硬件叠加的边界由 HWC 动态决定。

Android 多显示器集成核心数据流 应用 / Activity WindowManager 多显示窗口 SurfaceFlinger Layer 管理 · 合成调度 DisplayManagerService 逻辑显示 · 状态广播 HWC HAL 能力上报 · 合成决策 Overlay / Client 回退 Display 0(主屏) 独立 Layer 栈 · 刷新率 独立色彩空间 Display 1(副屏) 独立 Layer 栈 · 刷新率 独立色彩空间 Display N(虚拟/扩展) Virtual Display 按需创建与销毁 显示驱动 / DRM-KMS CRTC · Plane · Encoder · Connector 物理屏 0 物理屏 1 虚拟/远程屏

四、实战路线图:按阶段推进,避免“一上来就改 HWC”

多显示器集成工程最忌讳“先改代码再理解链路”。建议按以下五个阶段推进,每个阶段都有明确的交付物和验证手段。

阶段 核心任务 关键交付物 验证方式
1. 链路认知 梳理 App→SF→HWC→驱动→屏 的完整通路 数据流图、模块职责表 能口述每层输入输出
2. 环境搭建 确认 HWC 版本、显示接口、调试通道 可编译的 HWC 模块、dumpsys 基线 dumpsys SurfaceFlinger 正常输出
3. 单屏打通 先让主屏在 HWC 下稳定合成 Overlay 使用率、帧率基线 systrace 无异常掉帧
4. 多屏扩展 增加副屏、处理热插拔与独立合成 多 Display 配置、热插拔回调 插拔 50 次无黑屏/崩溃
5. 性能与量产 带宽评估、延迟优化、异常恢复 性能报告、排障手册 长时间压测稳定

五、典型场景与常见误区

以车载双屏为例:中控屏与仪表屏通常要求独立显示、独立刷新率,仪表屏对延迟极其敏感。此时 HWC 需要为两个 Display 分别维护图层栈,并优先保证仪表屏走硬件叠加。若把仪表屏图层错误地回退到 GPU 合成,延迟会明显上升,甚至出现撕裂。

常见误区一:认为“多显示器就是多开一个 Surface”。实际上,Surface 只是生产者端,真正的难点在 SurfaceFlinger 与 HWC 如何为每个显示设备组织合成。
常见误区二:忽略 HWC 能力上报。不同厂商 HWC 支持的 Overlay 数量、缩放能力、色彩格式不同,盲目假设“都能硬件合成”会导致回退和性能塌陷。
常见误区三:热插拔只处理“插入”,不处理“拔出”和“异常重连”。量产环境里,拔出时的资源释放和状态清理往往才是崩溃高发点。

六、调试入口:先学会看,再学会改

在动手改 HWC 之前,先掌握几条最常用的观察命令。它们能帮你快速判断当前显示状态、合成方式和图层归属。

# 查看当前显示设备与逻辑显示映射
adb shell dumpsys display

# 查看 SurfaceFlinger 合成状态与 HWC 信息
adb shell dumpsys SurfaceFlinger

# 抓取显示相关 trace(含 HWC 合成决策)
adb shell atrace -t 5 -b 8192 gfx view sched freq

# 查看 HWC 能力与显示配置(厂商实现路径可能不同)
adb shell dumpsys SurfaceFlinger --display-id

建议在课程初期就建立一份“基线记录”:主屏在默认配置下的帧率、Overlay 使用数量、GPU 合成占比、热插拔耗时。后续任何修改都与此基线对比,才能判断优化是否真正有效。

学习本课程时,请始终带着三个问题:这条链路中谁负责决策?决策依据是什么?决策失败时如何回退?把这三个问题贯穿到每一节,多显示器集成就不再是零散知识点的堆砌,而是一套可推演、可验证的工程方法。