在 Android 9 及更低版本中,SurfaceFlinger 和 DisplayManagerService
假设最多存在两个实体屏幕,其硬编码 ID 分别为 0 和 1。如静态屏幕标识符中所述,SurfaceFlinger 现在利用硬件混合渲染器 (HWC) API 生成稳定的屏幕 ID,使其能够管理任意数量的物理屏幕。
在从 SurfaceControl#getPhysicalDisplayIds
或 DisplayEventReceiver
热插拔事件获取 64 位屏幕 ID 后,框架可以通过 SurfaceControl#getPhysicalDisplayToken
查找物理屏幕的 IBinder
令牌。
在 Android 10 中,主内部屏幕为 TYPE_BUILT_IN
,所有辅助屏幕都将标记为 TYPE_HDMI
(无论连接类型如何)。因此,其他内部屏幕目前被视为外部屏幕。解决方法是,如果 HWC 已知且端口分配逻辑可预测,特定于设备的代码可以对 DisplayAddress.Physical#getPort
作出假设。
实现
以前,屏幕使用 32 位 ID 表示,其中 0 表示内部屏幕,1 表示外部屏幕,[2, INT32_MAX] 表示 HWC 虚拟屏幕,而 -1 表示无效屏幕或非 HWC 虚拟屏幕。为了使 SurfaceFlinger 和 DisplayManagerService
能够跟踪两个以上的屏幕并识别以前看到的屏幕,应该为屏幕提供稳定持久的 ID。
如果 HWC 支持 IComposerClient.getDisplayIdentificationData
并提供屏幕标识数据,SurfaceFlinger 将会解析 EDID 结构,并为实体屏幕和 HWC 虚拟屏幕分配稳定的 64 位屏幕 ID。系统会使用选项类型表示 ID,其中空值表示无效屏幕或非 HWC 虚拟屏幕。如果 HWC 不支持,SurfaceFlinger 会回退到最多只存在两个物理屏幕的旧版行为。