From 70fcab76a4dcf65e628ac897620fe050758574e3 Mon Sep 17 00:00:00 2001 From: Brett Lavalla Date: Wed, 13 Apr 2022 16:05:29 -0700 Subject: [PATCH] Fix RN accessibility links with UIAutomator Summary: D34687371 (https://github.com/facebook/react-native/commit/7b5b114d578142d18bf4a7a5279b179a9ac8d958) unfortunately caused a regression with UIAutomator, where it would no longer be able to see any Views that have the ReactAccessibilityDelegate attached to them. This was because the delegate was changed to extend ExploreByTouchHelper which implements its own default AccessibilityNodeProvider, which does nothing in the case of a view without any virtual children. This diff simply *only* uses the node provider if the view in question has virtual children, otherwise defaulting to the standard behavior from the View class. Changelog: [Android][Fixed] - Fixed issue where any node with an AccessibilityDelegate set (which was any node with any accessibility propoerty), was using ExploreByTouchHelper's built in AccessibilityNodeProvider, and not properly populating their AccessibilityNodeInfo's, leading to focus issues and issues with automated test services like UIAutomator. Reviewed By: kacieb Differential Revision: D35601320 fbshipit-source-id: 92e009c6e8b4ddcab860e2c91e6bd1a8f95359f0 --- .../uimanager/ReactAccessibilityDelegate.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index 04f0684dc95..7d38333ccf3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -27,6 +27,7 @@ import androidx.core.view.ViewCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat; +import androidx.core.view.accessibility.AccessibilityNodeProviderCompat; import androidx.customview.widget.ExploreByTouchHelper; import com.facebook.react.R; import com.facebook.react.bridge.Arguments; @@ -684,4 +685,20 @@ public class ReactAccessibilityDelegate extends ExploreByTouchHelper { public int id; } } + + @Override + public @Nullable AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) { + // Only set a NodeProvider if we have virtual views, otherwise just return null here so that + // we fall back to the View class's default behavior. If we don't do this, then Views with + // no virtual children will fall back to using ExploreByTouchHelper's onPopulateNodeForHost + // method to populate their AccessibilityNodeInfo, which defaults to doing nothing, so no + // AccessibilityNodeInfo will be created. Alternatively, we could override + // onPopulateNodeForHost instead, and have it create an AccessibilityNodeInfo for the host + // but this is what the default View class does by itself, so we may as well defer to it. + if (mAccessibilityLinks != null) { + return super.getAccessibilityNodeProvider(host); + } + + return null; + } }