fix: BufferQueue abandoned导致进程崩溃重启

- 采集循环每帧检测imageReader.surface.isValid, Surface失效时立即回退到无障碍截图
- setupMediaProjectionResources中VirtualDisplay创建后验证Surface有效性
- 采集循环中VirtualDisplay重建后验证Surface有效性, 无效则直接回退
- reinitializeVirtualDisplayForAndroid15中重建后验证Surface有效性
- 清理drainImageReader注释中的乱码字符
This commit is contained in:
wdvipa
2026-02-15 01:01:33 +08:00
parent 87b84b01bb
commit e93286cf31

View File

@@ -192,7 +192,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
}
/**
* <20> 清空ImageReader中所有已acquired的Image释放缓冲区槽位
* 清空ImageReader中所有已acquired的Image释放缓冲区槽位
* 当acquireLatestImage抛出maxImages异常时调用
*/
private fun drainImageReader() {
@@ -450,6 +450,21 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
while (isCapturing) {
try {
// Surface有效性检测BufferQueue被系统abandoned后立即回退
// 防止acquireLatestImage()持续返回null触发无限重建循环
val currentSurface = imageReader?.surface
if (currentSurface == null || !currentSurface.isValid) {
Log.w(TAG, "ImageReader Surface已失效(null=${currentSurface == null}, isValid=${currentSurface?.isValid}), 停止采集并回退到无障碍截图")
cleanupVirtualDisplayOnly()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
enableAccessibilityScreenshotMode()
startAccessibilityScreenCapture()
} else {
startFallbackCapture()
}
return@launch
}
// 安全获取Image防止maxImages溢出
val image = try {
imageReader?.acquireLatestImage()
@@ -563,8 +578,11 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
setupMediaProjectionResources()
consecutiveFailures = 0
if (virtualDisplay == null) {
Log.w(TAG, "VirtualDisplay 重建失败,回退到无障碍截图")
// 重建后验证VirtualDisplay和Surface有效性
val rebuiltSurface = imageReader?.surface
if (virtualDisplay == null || rebuiltSurface == null || !rebuiltSurface.isValid) {
Log.w(TAG, "VirtualDisplay 重建后无效(vd=${virtualDisplay != null}, surface=${rebuiltSurface != null}, valid=${rebuiltSurface?.isValid}), 回退到无障碍截图")
cleanupVirtualDisplayOnly()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
enableAccessibilityScreenshotMode()
startAccessibilityScreenCapture()
@@ -1222,6 +1240,17 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
if (virtualDisplay != null) {
Log.i(TAG, "VirtualDisplay创建成功")
// 验证Surface有效性防止BufferQueue已被abandoned
val createdSurface = imageReader?.surface
if (createdSurface == null || !createdSurface.isValid) {
Log.e(TAG, "VirtualDisplay创建后Surface无效(null=${createdSurface == null}, isValid=${createdSurface?.isValid}), 清理资源")
virtualDisplay?.release()
virtualDisplay = null
imageReader?.close()
imageReader = null
return
}
// Android 15VirtualDisplay创建成功后触发权限申请处理
if (Build.VERSION.SDK_INT >= 35) {
Log.i(TAG, "Android 15VirtualDisplay创建成功触发权限申请处理")
@@ -2462,6 +2491,18 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
if (virtualDisplay != null) {
Log.i(TAG, "Android 15 VirtualDisplay完全重新创建成功")
// 验证Surface有效性
val rebuiltSurface = imageReader?.surface
if (rebuiltSurface == null || !rebuiltSurface.isValid) {
Log.e(TAG, "Android 15 VirtualDisplay重建后Surface无效, 放弃")
virtualDisplay?.release()
virtualDisplay = null
imageReader?.close()
imageReader = null
isVirtualDisplayRecreating = false
return false
}
// Android 15VirtualDisplay重新创建成功后触发权限申请处理
Log.i(TAG, "Android 15VirtualDisplay重新创建成功触发权限申请处理")
triggerAndroid15PermissionRequest("重新初始化VirtualDisplay")