diff options
| author | 2016-04-07 21:01:57 -0700 | |
|---|---|---|
| committer | 2016-04-08 13:06:44 -0700 | |
| commit | e37cfab6c65ec0997b07089e70fa0ad47d2fbd83 (patch) | |
| tree | da944d70c8f0520f6fb4d9bb424b02c5d38965e9 | |
| parent | 4a62effbfe8ad9a0eb7049c2f52a57d39bb64e29 (diff) | |
Reduce unnecessary accessibility cache clearing.
Tracking if accessibility focus is being cleared because it is being
set to another view in the same window. In this case, leave
accessibility focus on the window.
This change greatly reduces the amount of cache re-indexing.
Previously we flushed the cache every time accessibility focus moved.
Bug: 28077283
Change-Id: If80899d36e7f58b22635f844bdd4ea37a55b875e
3 files changed, 32 insertions, 13 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index b0aa5c3a77e0..7e5109637855 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8877,7 +8877,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ public void clearAccessibilityFocus() { - clearAccessibilityFocusNoCallbacks(); + clearAccessibilityFocusNoCallbacks(0); // Clear the global reference of accessibility focus if this view or // any of its descendants had accessibility focus. This will NOT send @@ -8920,14 +8920,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Clears accessibility focus without calling any callback methods * normally invoked in {@link #clearAccessibilityFocus()}. This method - * is used for clearing accessibility focus when giving this focus to - * another view. + * is used separately from that one for clearing accessibility focus when + * giving this focus to another view. + * + * @param action The action, if any, that led to focus being cleared. Set to + * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within + * the window. */ - void clearAccessibilityFocusNoCallbacks() { + void clearAccessibilityFocusNoCallbacks(int action) { if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) { mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED; invalidate(); - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + if (AccessibilityManager.getInstance(mContext).isEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain( + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + event.setAction(action); + if (mAccessibilityDelegate != null) { + mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); + } else { + sendAccessibilityEventUnchecked(event); + } + } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 5b2877faef02..a324767ac4ed 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3071,7 +3071,8 @@ public final class ViewRootImpl implements ViewParent, // Clear accessibility focus on the host after clearing state since // this method may be reentrant. - focusHost.clearAccessibilityFocusNoCallbacks(); + focusHost.clearAccessibilityFocusNoCallbacks( + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); AccessibilityNodeProvider provider = focusHost.getAccessibilityNodeProvider(); if (provider != null) { @@ -3088,7 +3089,8 @@ public final class ViewRootImpl implements ViewParent, } if (mAccessibilityFocusedHost != null) { // Clear accessibility focus in the view. - mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks(); + mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks( + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); } // Set the new focus host and node. @@ -6623,7 +6625,7 @@ public final class ViewRootImpl implements ViewParent, // Error state: virtual view with no provider. Clear focus. mAccessibilityFocusedHost = null; mAccessibilityFocusedVirtualView = null; - focusedHost.clearAccessibilityFocusNoCallbacks(); + focusedHost.clearAccessibilityFocusNoCallbacks(0); return; } @@ -6673,7 +6675,7 @@ public final class ViewRootImpl implements ViewParent, if (mAccessibilityFocusedVirtualView == null) { // Error state: The node no longer exists. Clear focus. mAccessibilityFocusedHost = null; - focusedHost.clearAccessibilityFocusNoCallbacks(); + focusedHost.clearAccessibilityFocusNoCallbacks(0); // This will probably fail, but try to keep the provider's internal // state consistent by clearing focus. diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 27417332f7d1..adf44d40de5c 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -439,7 +439,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) { mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(), - event.getSourceNodeId(), event.getEventType()); + event.getSourceNodeId(), event.getEventType(), event.getAction()); mSecurityPolicy.updateEventSourceLocked(event); notifyAccessibilityServicesDelayedLocked(event, false); notifyAccessibilityServicesDelayedLocked(event, true); @@ -3829,7 +3829,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, - int eventType) { + int eventType, int eventAction) { // The active window is either the window that has input focus or // the window that the user is currently touching. If the user is // touching a window that does not have input focus as soon as the @@ -3882,8 +3882,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (mAccessibilityFocusNodeId == nodeId) { mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; } - if (mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID - && mAccessibilityFocusedWindowId == windowId) { + // Clear the window with focus if it no longer has focus and we aren't + // just moving focus from one view to the other in the same window + if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) + && (mAccessibilityFocusedWindowId == windowId) + && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) + ) { mAccessibilityFocusedWindowId = INVALID_WINDOW_ID; } } |