Surface黑花闪
Alpha 限制在 [0.01, 0.99] 的原因
对应代码(L420):
val alpha = (1 - progress).coerceIn(0.01f, 0.99f)
问题一:alpha = 0f 会导致 Layer 被 hide
这是 SurfaceFlinger 的内部行为:当一个 Layer 的 alpha 被设为 0f(完全透明),SF 会认为”这个 Layer 没有任何可见内容”,自动将其标记为 hidden,从合成管线中移除。
后果:
动画进度 progress = 1.0f → alpha = 1 - 1.0 = 0.0f
│
▼
SurfaceFlinger 自动 hide Layer
│
▼
Layer 状态变为 hidden,但代码中
mSurfaceVisible 仍然是 true
│
▼
状态不一致 → 下次 show/hide 逻辑出错设 0.01f 时,Layer 保持 visible 状态在合成管线中,但人眼完全看不出来(不透明度只有 1%)。代码自己掌控 hide 时机(动画结束回调里主动调用 hideSurface())。
问题二:alpha = 1f 会花屏(BUGOS2-139460)
这是一个硬件/驱动层的 bug。当 ColorLayer 的 alpha 精确等于 1.0f 时,某些 GPU/显示驱动在合成路径上会出现异常渲染(花屏)。
可能的底层原因(常见于 Qualcomm/MTK HWC 实现):
- alpha = 1.0f 的 ColorLayer 触发了 HWC(Hardware Composer)的特殊优化路径——直接覆盖而不做 alpha blending
- 该优化路径在特定 shader/ColorLayer 组合下存在 bug,导致花屏
- alpha = 0.99f 走的是正常 alpha blending 路径,绕开了有问题的优化分支
设 0.99f 时,视觉上与全黑无差异(只差 1% 透明度),但强制走 blending 路径,规避驱动 bug。
总结

这是 Android 系统开发中典型的 workaround 模式——用肉眼不可感知的微小偏移,绕开底层组件的边界条件 bug。
源码中的应用
private fun showScreenFadeSurface(progress: Float, needShow: Boolean,
coverBlack :Boolean, onWakingUp:Boolean = false): Boolean {
synchronized(mScreenFadeLocked) {
if (!ensureSurfaceControlCreated()) {
if (onWakingUp) {
mCoverBlackScreenWakingUp = false
}
return false
}
if (onWakingUp) {
mCoverBlackScreenWakingUp = true
}
if (coverBlack && mSurfaceVisible) {
if (DEBUG) {
Log.d(TAG, "ScreenFade has visible progress $mSurfaceProgress")
}
return true
}
if (!mSurfaceVisible || mSurfaceProgress != progress) {
mScreenFadeSurfaceControl?.let {
// alpha 设置为0f layer就回直接hide 不能设0f,设0.01f
// alpha 设置为1f 会有花屏问题 不能设1f,设0.99f workaround:BUGOS2-139460
val alpha = (1 - progress).coerceIn(0.01f, 0.99f)
mScreenFadeTransaction.setAlpha(it, alpha)
setScreenFadeToSf(it, progress)
if (needShow) {
Log.d(TAG, "ScreenFade show ScreenFade layer progress: $progress")
mScreenFadeTransaction.show(mScreenFadeSurfaceControl)
}
if (!mMergeWithNextTransaction) {
mScreenFadeTransaction.applyAsyncUnsafe()
}
mSurfaceVisible = true
mSurfaceProgress = progress
}
}
return true
}
}