@@ -488,7 +488,9 @@ public void setView(View view, WindowManager.LayoutParams attrs, View panelParen
488488 mFallbackEventHandler .setView (view );
489489 mWindowAttributes .copyFrom (attrs );
490490 attrs = mWindowAttributes ;
491-
491+
492+ setAccessibilityFocusedHost (null );
493+
492494 if (view instanceof RootViewSurfaceTaker ) {
493495 mSurfaceHolderCallback =
494496 ((RootViewSurfaceTaker )view ).willYouTakeTheSurface ();
@@ -556,6 +558,7 @@ public void setView(View view, WindowManager.LayoutParams attrs, View panelParen
556558 mInputChannel = null ;
557559 mFallbackEventHandler .setView (null );
558560 unscheduleTraversals ();
561+ setAccessibilityFocusedHost (null );
559562 throw new RuntimeException ("Adding window failed" , e );
560563 } finally {
561564 if (restore ) {
@@ -575,6 +578,7 @@ public void setView(View view, WindowManager.LayoutParams attrs, View panelParen
575578 mAdded = false ;
576579 mFallbackEventHandler .setView (null );
577580 unscheduleTraversals ();
581+ setAccessibilityFocusedHost (null );
578582 switch (res ) {
579583 case WindowManagerImpl .ADD_BAD_APP_TOKEN :
580584 case WindowManagerImpl .ADD_BAD_SUBWINDOW_TOKEN :
@@ -635,8 +639,6 @@ public void setView(View view, WindowManager.LayoutParams attrs, View panelParen
635639 if (view .getImportantForAccessibility () == View .IMPORTANT_FOR_ACCESSIBILITY_AUTO ) {
636640 view .setImportantForAccessibility (View .IMPORTANT_FOR_ACCESSIBILITY_YES );
637641 }
638-
639- setAccessibilityFocusedHost (null );
640642 }
641643 }
642644 }
@@ -2543,11 +2545,51 @@ public AccessibilityNodeInfo getAccessibilityFocusedVirtualView() {
25432545 }
25442546
25452547 void setAccessibilityFocusedHost (View host ) {
2546- if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView == null ) {
2548+ // If we have a virtual view with accessibility focus we need
2549+ // to clear the focus and invalidate the virtual view bounds.
2550+ if (mAccessibilityFocusedVirtualView != null ) {
2551+
2552+ AccessibilityNodeInfo focusNode = mAccessibilityFocusedVirtualView ;
2553+ View focusHost = mAccessibilityFocusedHost ;
2554+ focusHost .clearAccessibilityFocusNoCallbacks ();
2555+
2556+ // Wipe the state of the current accessibility focus since
2557+ // the call into the provider to clear accessibility focus
2558+ // will fire an accessibility event which will end up calling
2559+ // this method and we want to have clean state when this
2560+ // invocation happens.
2561+ mAccessibilityFocusedHost = null ;
2562+ mAccessibilityFocusedVirtualView = null ;
2563+
2564+ AccessibilityNodeProvider provider = focusHost .getAccessibilityNodeProvider ();
2565+ if (provider != null ) {
2566+ // Invalidate the area of the cleared accessibility focus.
2567+ focusNode .getBoundsInParent (mTempRect );
2568+ focusHost .invalidate (mTempRect );
2569+ // Clear accessibility focus in the virtual node.
2570+ final int virtualNodeId = AccessibilityNodeInfo .getVirtualDescendantId (
2571+ focusNode .getSourceNodeId ());
2572+ provider .performAction (virtualNodeId ,
2573+ AccessibilityNodeInfo .ACTION_CLEAR_ACCESSIBILITY_FOCUS , null );
2574+ }
2575+ }
2576+ if (mAccessibilityFocusedHost != null ) {
2577+ // Clear accessibility focus in the view.
25472578 mAccessibilityFocusedHost .clearAccessibilityFocusNoCallbacks ();
25482579 }
2580+
2581+ // Set the new focus host.
25492582 mAccessibilityFocusedHost = host ;
2550- mAccessibilityFocusedVirtualView = null ;
2583+
2584+ // If the host has a provide find the virtual descendant that has focus.
2585+ if (mAccessibilityFocusedHost != null ) {
2586+ AccessibilityNodeProvider provider =
2587+ mAccessibilityFocusedHost .getAccessibilityNodeProvider ();
2588+ if (provider != null ) {
2589+ mAccessibilityFocusedVirtualView = provider .findAccessibilityFocus (View .NO_ID );
2590+ return ;
2591+ }
2592+ }
25512593 }
25522594
25532595 public void requestChildFocus (View child , View focused ) {
@@ -2633,6 +2675,8 @@ void dispatchDetachedFromWindow() {
26332675
26342676 destroyHardwareRenderer ();
26352677
2678+ setAccessibilityFocusedHost (null );
2679+
26362680 mView = null ;
26372681 mAttachInfo .mRootView = null ;
26382682 mAttachInfo .mSurface = null ;
@@ -4608,6 +4652,31 @@ public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent even
46084652 if (mView == null ) {
46094653 return false ;
46104654 }
4655+ // Watch for accessibility focus change events from virtual nodes
4656+ // to keep track of accessibility focus being on a virtual node.
4657+ final int eventType = event .getEventType ();
4658+ switch (eventType ) {
4659+ case AccessibilityEvent .TYPE_VIEW_ACCESSIBILITY_FOCUSED : {
4660+ final long sourceId = event .getSourceNodeId ();
4661+ // If the event is not from a virtual node we are not interested.
4662+ final int virtualViewId = AccessibilityNodeInfo .getVirtualDescendantId (sourceId );
4663+ if (virtualViewId == AccessibilityNodeInfo .UNDEFINED ) {
4664+ break ;
4665+ }
4666+ final int realViewId = AccessibilityNodeInfo .getAccessibilityViewId (sourceId );
4667+ View focusHost = mView .findViewByAccessibilityId (realViewId );
4668+ setAccessibilityFocusedHost (focusHost );
4669+ } break ;
4670+ case AccessibilityEvent .TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED : {
4671+ final long sourceId = event .getSourceNodeId ();
4672+ // If the event is not from a virtual node we are not interested.
4673+ final int virtualViewId = AccessibilityNodeInfo .getVirtualDescendantId (sourceId );
4674+ if (virtualViewId == AccessibilityNodeInfo .UNDEFINED ) {
4675+ break ;
4676+ }
4677+ setAccessibilityFocusedHost (null );
4678+ } break ;
4679+ }
46114680 mAccessibilityManager .sendAccessibilityEvent (event );
46124681 return true ;
46134682 }
0 commit comments