From e93286cf31f93276832ac109e3758f16332542f5 Mon Sep 17 00:00:00 2001 From: wdvipa Date: Sun, 15 Feb 2026 01:01:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20BufferQueue=20abandoned=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E8=BF=9B=E7=A8=8B=E5=B4=A9=E6=BA=83=E9=87=8D=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 采集循环每帧检测imageReader.surface.isValid, Surface失效时立即回退到无障碍截图 - setupMediaProjectionResources中VirtualDisplay创建后验证Surface有效性 - 采集循环中VirtualDisplay重建后验证Surface有效性, 无效则直接回退 - reinitializeVirtualDisplayForAndroid15中重建后验证Surface有效性 - 清理drainImageReader注释中的乱码字符 --- .../hikoncont/manager/ScreenCaptureManager.kt | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt b/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt index f13b07a..2124065 100644 --- a/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt +++ b/app/src/main/java/com/hikoncont/manager/ScreenCaptureManager.kt @@ -192,7 +192,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) { } /** - * � 清空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 15:VirtualDisplay创建成功后触发权限申请处理 if (Build.VERSION.SDK_INT >= 35) { Log.i(TAG, "Android 15:VirtualDisplay创建成功,触发权限申请处理") @@ -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 15:VirtualDisplay重新创建成功后触发权限申请处理 Log.i(TAG, "Android 15:VirtualDisplay重新创建成功,触发权限申请处理") triggerAndroid15PermissionRequest("重新初始化VirtualDisplay")