From 8e3885218a64a9846d5147577fbd580794db71c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Thu, 22 Oct 2026 08:59:52 +0200 Subject: [PATCH] fix(android): read a child that vanished mid-read as gone AccessibilityNodeInfo.getChild can throw a NullPointerException from the framework's result integrity check when the child's window closes during the read, for example while an alert dialog closes after `alert accept`. The persistent helper session reported that as a capture failure, so the host force-killed the session, answered with a one-shot capture, and kept the session off for about 40 s. Treat the throw as the null that the framework answers for a vanished child. Co-Authored-By: Claude Opus 5.5 --- .../snapshothelper/AccessibilityNodeReads.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/android/snapshot-helper/src/main/java/com/callstack/agentdevice/snapshothelper/AccessibilityNodeReads.java b/android/snapshot-helper/src/main/java/com/callstack/agentdevice/snapshothelper/AccessibilityNodeReads.java index bfbd928f49..752e0429cb 100644 --- a/android/snapshot-helper/src/main/java/com/callstack/agentdevice/snapshothelper/AccessibilityNodeReads.java +++ b/android/snapshot-helper/src/main/java/com/callstack/agentdevice/snapshothelper/AccessibilityNodeReads.java @@ -30,10 +30,19 @@ static AccessibilityNodeInfo root(AccessibilityWindowInfo window) { return window.getRoot(); } + /** + * The child, or null when it is gone. When the child's window closes during the read, the + * framework can throw a NullPointerException from its result integrity check instead of answering + * null (seen on API 35 while an alert dialog closed), so that throw means the same as null. + */ static AccessibilityNodeInfo child(AccessibilityNodeInfo node, int index) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - return node.getChild(index, PREFETCH_STRATEGY); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return node.getChild(index, PREFETCH_STRATEGY); + } + return node.getChild(index); + } catch (NullPointerException vanished) { + return null; } - return node.getChild(index); } }