4. Android显示框架

在骁龙8295座舱平台上,多屏显示不是“多接几根线”那么简单。Android的显示框架由应用侧、系统服务侧和硬件抽象侧共同构成,任何一帧画面从App绘制到最终出现在仪表屏、中控屏或副驾屏上,都要经过BufferQueue、SurfaceFlinger、HWC和DisplayManager的协同。理解这条链路,是后续做多屏性能优化的前提。

一、核心角色与职责边界

Android显示框架中,四个核心对象各司其职:

  • SurfaceFlinger:系统合成服务,负责管理所有Layer、决定合成策略、调用HWC或GPU完成最终合成,并把结果提交给显示设备。
  • HWC(Hardware Composer):硬件合成器抽象层,由SoC厂商实现。它决定哪些Layer可以走硬件Overlay、哪些必须由GPU合成,并负责把最终图层送到Display Engine。
  • DisplayManager:显示设备管理服务,负责枚举物理屏、管理逻辑显示、处理分辨率/刷新率/旋转等配置,并向应用暴露Display对象。
  • Layer:每个Surface对应一个Layer,携带Buffer、位置、缩放、透明度、Z-order、裁剪等属性,是合成的基本单位。
关键理解:SurfaceFlinger不是“画图”的,它是“合成调度器”;HWC不是“必须用”的,它是“能省则省”的硬件加速路径。多屏性能优化的核心,就是让尽可能多的Layer走HWC Overlay,减少GPU合成和跨屏拷贝。

二、Layer合成流程:从App到屏幕

一帧的完整生命周期可以拆成六个阶段:

  1. App绘制:应用通过Skia/Vulkan把内容画进GraphicBuffer,通过BufferQueue入队。
  2. SurfaceFlinger收集:SF在vsync到来时遍历所有Layer,读取每个Layer的Buffer和属性,形成合成列表。
  3. 合成策略决策:SF把Layer列表交给HWC,HWC根据硬件能力返回每个Layer的合成方式(Overlay或GPU)。
  4. GPU合成:被判定为GPU合成的Layer,由SF用RenderEngine画到一张新的Buffer上。
  5. HWC提交:HWC把Overlay Layer和GPU合成结果一起提交给Display Engine。
  6. 扫描输出:Display Engine按vsync把画面送到物理屏。

在8295上,HWC通常支持多层Overlay,但每个Display的Overlay数量有限。当Layer数量超过硬件能力,或出现跨屏缩放、旋转、Alpha混合等复杂操作时,就会触发GPU合成,带来额外功耗和延迟。

Android 显示框架:Layer 合成与多屏适配链路 应用进程 App Surface / Canvas BufferQueue 入队 GraphicBuffer SurfaceFlinger Layer 列表 / Z-order 合成策略决策 RenderEngine (GPU) HWC / Display Engine Overlay 判定 硬件图层合成 扫描输出 DisplayManager 物理屏枚举 逻辑显示配置 分辨率/刷新率 多屏适配机制:Display 映射与合成资源分配 仪表屏 Display 0 1920×720 @60Hz Layer: 仪表UI + 报警 Overlay 预算: 4 层 中控屏 Display 1 2560×1440 @60Hz Layer: 导航 + 媒体 + 状态 Overlay 预算: 6 层 副驾屏 Display 2 1920×1080 @60Hz Layer: 视频 + 娱乐 Overlay 预算: 4 层 跨屏 跨屏 多屏场景下,SurfaceFlinger 需为每个 Display 维护独立合成列表;HWC 按 Display 分配 Overlay 资源,跨屏 Layer 易触发 GPU 合成。

三、多屏适配机制:Display 映射与资源分配

8295座舱通常有3~4块物理屏,Android通过DisplayManager把它们抽象成Display对象。每个Display有独立的合成列表、刷新率和Overlay预算。多屏适配的关键点包括:

  • Display映射:物理屏通过HWC的display接口注册,DisplayManager为其创建Logical Display,应用通过DisplayManager.getDisplay()获取。
  • 合成列表隔离:每个Display有独立的Layer列表,SurfaceFlinger按Display分别调用HWC的prepare/set接口。
  • Overlay预算分配:HWC为每个Display维护可用的Overlay层数,超出部分回退GPU合成。
  • 跨屏Layer:当Layer需要从一个Display移动到另一个Display时,会触发Buffer重分配和合成路径切换,是性能热点。
在8295上,仪表屏和中控屏通常由不同的Display Engine驱动。如果应用把仪表UI和中控UI放在同一个Surface里再跨屏显示,会导致HWC无法拆分Overlay,直接触发GPU合成。正确做法是按Display拆分Surface。

四、案例:多屏导航+视频场景的合成路径

假设中控屏显示导航地图,副驾屏播放视频,仪表屏显示车速。三块屏的Layer构成如下:

Display Layer 合成方式 原因
仪表屏 车速UI HWC Overlay 单层、无缩放、无Alpha
仪表屏 报警弹窗 HWC Overlay 小尺寸、位置固定
中控屏 导航地图 GPU合成 地图纹理频繁更新,HWC不支持动态纹理
中控屏 状态栏 HWC Overlay 静态、小尺寸
副驾屏 视频层 HWC Overlay 视频层走硬件视频通道
副驾屏 弹幕/字幕 GPU合成 Alpha混合、频繁更新

这个场景中,中控屏的导航地图和副驾屏的字幕是GPU合成的主要来源。优化方向是:把导航地图拆成静态底图和动态图层,静态底图走Overlay;字幕层降低更新频率或改用硬件字幕通道。

五、常见误区与复盘

误区一:认为“所有Layer都能走HWC”。实际上HWC的Overlay数量有限,且对缩放、旋转、Alpha、格式有约束。误区二:认为“GPU合成一定慢”。GPU合成在Layer数量少时可能比HWC更省电,关键看场景。误区三:忽略DisplayManager的配置影响。分辨率、刷新率、旋转角度的变化会直接改变HWC的合成能力。

复盘时建议抓取以下信息:

# 查看当前Display信息
adb shell dumpsys display | grep -E "DisplayDeviceInfo|mDisplayId|refreshRate"

# 查看SurfaceFlinger Layer合成方式
adb shell dumpsys SurfaceFlinger --list
adb shell dumpsys SurfaceFlinger | grep -E "HWC|GPU|Overlay|Composition"

# 查看HWC能力
adb shell dumpsys SurfaceFlinger | grep -A 20 "Hardware Composer"

通过dumpsys可以看到每个Layer的合成类型(HWC或GPU)、每个Display的Overlay使用情况,以及是否存在跨屏Layer。这些数据是后续做多屏性能优化的基础。

总结来说,SurfaceFlinger负责调度,HWC负责硬件加速,DisplayManager负责多屏管理,Layer是合成的基本单位。多屏性能优化的核心,是让每个Display的Layer数量控制在Overlay预算内,减少GPU合成和跨屏拷贝,从而降低功耗和延迟。