问题现象

副屏播放爱奇艺视频,快速熄屏亮屏时,主屏概率性黑屏,原因是副屏的视频 SurfaceView 的背景显示在了主屏,所以看起来主屏黑了。

主屏

主屏

副屏

副屏

<aside> 🪅

该问题与 HUD 显示屏幕错误问题分析与修复 现象类似,都是其他屏幕的 layer 因为丢失 parent layer 但又重新设置 relative layer 导致显示在主屏上。

</aside>

问题分析

直接原因是副屏的视频 SurfaceView 的 Background layer显示在主屏,从 SurfaceFlinger dump 信息中可以确认。

Screenshot_2024-10-11_at_10.57.00.png

该 Background 是熄屏前创建的 layer,而不是亮屏之后创建的 layer,而且它在 Offscreen Layers 中。

image.png

从 log 确认,当熄屏时 Background 已经移除了 parent layer 和 relative layer。

10-10 11:16:35.248 18288 18288 I SurfaceFlinger: Reparenting +++++++++++++++++++++ layer Background for SurfaceView[xxx]#0 seq 414 parentHandle null
10-10 11:16:35.248 18288 18288 I Layer   : lxz removeChild: parent=SurfaceView[xxx]#0 layer=Background for SurfaceView[xxx]#0 removeResult=0
10-10 11:16:35.248 18288 18288 I Layer   : lxz Layer Background for SurfaceView[xxx]#0 onRemovedFromCurrentState
10-10 11:16:35.248 18288 18288 I Layer   : lxz setZOrderRelativeOf Background for SurfaceView[xxx]#0 seq 414, relative 0

<aside> 🏷️

Relative layer 指的是,设置了相对 z-order 的 layer。系统会给 SurfaceView 及它的 Background 设置 relative layer 为 SurfaceView 所在的 ViewRootImpl layer。

graph BT
SurfaceView-bufferlayer --parent--> SurfaceView-container-layer --parent--> Bounds-layer --parent--> ViewRootImpl-layer
SurfaceView-background-layer --parent--> SurfaceView-container-layer
SurfaceView-bufferlayer -.relative of.-> ViewRootImpl-layer
SurfaceView-background-layer -.relative of.-> ViewRootImpl-layer

</aside>

新增的 log 如下所示。

image.png

image.png

image.png

image.png

上面是正常的逻辑,当出现问题时,多了一次设置 relative layer 的 log。

10-10 11:16:35.266 18288 18288 I Layer   : lxz setZOrderRelativeOf Background for SurfaceView[xxx]#0 seq 414, relative xxx#0

SurfaceFlinger 合成时不仅遍历父子关系的 layer,同时遍历 relative 的 layer,所以熄屏前的 background layer 参与了合成。Background layer 本来在副屏,但是显示在主屏的原因是它的 parent layer 已经移除,所以显示在默认的屏幕,即主屏。