@@ -204,6 +204,70 @@ public void itAnnouncesRouteNameWhenAddingNewRoute() {
204204 assertEquals(sentences.get(0).toString(), "new_node2");
205205 }
206206
207+ @Test
208+ public void itIgnoresUnfocusableNodeDuringHitTest() {
209+ AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class);
210+ AccessibilityManager mockManager = mock(AccessibilityManager.class);
211+ View mockRootView = mock(View.class);
212+ Context context = mock(Context.class);
213+ when(mockRootView.getContext()).thenReturn(context);
214+ when(context.getPackageName()).thenReturn("test");
215+ AccessibilityBridge accessibilityBridge =
216+ setUpBridge(mockRootView, mockManager, mockViewEmbedder);
217+ ViewParent mockParent = mock(ViewParent.class);
218+ when(mockRootView.getParent()).thenReturn(mockParent);
219+ when(mockManager.isEnabled()).thenReturn(true);
220+ when(mockManager.isTouchExplorationEnabled()).thenReturn(true);
221+
222+ TestSemanticsNode root = new TestSemanticsNode();
223+ root.id = 0;
224+ root.left = 0;
225+ root.top = 0;
226+ root.bottom = 20;
227+ root.right = 20;
228+ TestSemanticsNode ignored = new TestSemanticsNode();
229+ ignored.id = 1;
230+ ignored.addFlag(AccessibilityBridge.Flag.SCOPES_ROUTE);
231+ ignored.left = 0;
232+ ignored.top = 0;
233+ ignored.bottom = 20;
234+ ignored.right = 20;
235+ root.children.add(ignored);
236+ TestSemanticsNode child = new TestSemanticsNode();
237+ child.id = 2;
238+ child.label = "label";
239+ child.left = 0;
240+ child.top = 0;
241+ child.bottom = 20;
242+ child.right = 20;
243+ root.children.add(child);
244+ TestSemanticsUpdate testSemanticsUpdate = root.toUpdate();
245+ accessibilityBridge.updateSemantics(testSemanticsUpdate.buffer, testSemanticsUpdate.strings);
246+
247+ ArgumentCaptor<AccessibilityEvent> eventCaptor =
248+ ArgumentCaptor.forClass(AccessibilityEvent.class);
249+ verify(mockParent, times(2))
250+ .requestSendAccessibilityEvent(eq(mockRootView), eventCaptor.capture());
251+ AccessibilityEvent event = eventCaptor.getAllValues().get(0);
252+ assertEquals(event.getEventType(), AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
253+
254+ // Synthesize an accessibility hit test event.
255+ MotionEvent mockEvent = mock(MotionEvent.class);
256+ when(mockEvent.getX()).thenReturn(10.0f);
257+ when(mockEvent.getY()).thenReturn(10.0f);
258+ when(mockEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
259+ boolean hit = accessibilityBridge.onAccessibilityHoverEvent(mockEvent);
260+
261+ assertEquals(hit, true);
262+
263+ eventCaptor = ArgumentCaptor.forClass(AccessibilityEvent.class);
264+ verify(mockParent, times(3))
265+ .requestSendAccessibilityEvent(eq(mockRootView), eventCaptor.capture());
266+ event = eventCaptor.getAllValues().get(2);
267+ assertEquals(event.getEventType(), AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
268+ assertEquals(accessibilityBridge.getHoveredObjectId(), 2);
269+ }
270+
207271 @Test
208272 public void itAnnouncesRouteNameWhenRemoveARoute() {
209273 AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class);
0 commit comments