Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27e2da7c authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Remove the accessibility focus search code.

1. In JellyBean we have added some APIs to search for next accessibility
   focus in various directions and set accessibility focus from hover.
   However, we have decided that there is not clean answer for how this
   should behave and the APIs were hidden. Now the accessibility service
  is responsible for that. The unused code is now taken out.

2. This patch also takes out the hidden attribute accessibiligyFocusable
   since we moved the responsibility for implementing focus search strategy
   to accessibility services and we did not need that for Jellybean which
   is a good sign that this is not needed. I general this is one less thing
   for an app developer to worry about. We can add this if needed later.

bug:6773816

Change-Id: I0c858d72c93a2b7ff1f8f35a08d33ec4b9eb85fd
parent 0a6101b2
Loading
Loading
Loading
Loading
+3 −32
Original line number Diff line number Diff line
@@ -574,40 +574,11 @@ final class AccessibilityInteractionController {
                root = mViewRootImpl.mView;
            }
            if (root != null && isShown(root)) {
                if ((direction & View.FOCUS_ACCESSIBILITY) ==  View.FOCUS_ACCESSIBILITY) {
                    AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
                    if (provider != null) {
                        next = provider.accessibilityFocusSearch(direction, virtualDescendantId);
                        if (next != null) {
                            return;
                        }
                    }
                    View nextView = root.focusSearch(direction);
                    while (nextView != null) {
                        // If the focus search reached a node with a provider
                        // we delegate to the provider to find the next one.
                        // If the provider does not return a virtual view to
                        // take accessibility focus we try the next view found
                        // by the focus search algorithm.
                        provider = nextView.getAccessibilityNodeProvider();
                        if (provider != null) {
                            next = provider.accessibilityFocusSearch(direction, View.NO_ID);
                            if (next != null) {
                                break;
                            }
                            nextView = nextView.focusSearch(direction);
                        } else {
                            next = nextView.createAccessibilityNodeInfo();
                            break;
                        }
                    }
                } else {
                View nextView = root.focusSearch(direction);
                if (nextView != null) {
                    next = nextView.createAccessibilityNodeInfo();
                }
            }
            }
        } finally {
            try {
                mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+11 −34
Original line number Diff line number Diff line
@@ -79,17 +79,9 @@ public class FocusFinder {
    }

    private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
        if ((direction & View.FOCUS_ACCESSIBILITY) != View.FOCUS_ACCESSIBILITY) {
            return findNextInputFocus(root, focused, focusedRect, direction);
        } else {
            return findNextAccessibilityFocus(root, focused, focusedRect, direction);
        }
    }

    private View findNextInputFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
        View next = null;
        if (focused != null) {
            next = findNextUserSpecifiedInputFocus(root, focused, direction);
            next = findNextUserSpecifiedFocus(root, focused, direction);
        }
        if (next != null) {
            return next;
@@ -107,7 +99,7 @@ public class FocusFinder {
        return next;
    }

    private View findNextUserSpecifiedInputFocus(ViewGroup root, View focused, int direction) {
    private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
        // check for user specified next focus
        View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
        if (userSetNextFocus != null && userSetNextFocus.isFocusable()
@@ -120,7 +112,6 @@ public class FocusFinder {

    private View findNextFocus(ViewGroup root, View focused, Rect focusedRect,
            int direction, ArrayList<View> focusables) {
        final int directionMasked = (direction & ~View.FOCUS_ACCESSIBILITY);
        if (focused != null) {
            if (focusedRect == null) {
                focusedRect = mFocusedRect;
@@ -132,7 +123,7 @@ public class FocusFinder {
            if (focusedRect == null) {
                focusedRect = mFocusedRect;
                // make up a rect at top left or bottom right of root
                switch (directionMasked) {
                switch (direction) {
                    case View.FOCUS_RIGHT:
                    case View.FOCUS_DOWN:
                        setFocusTopLeft(root, focusedRect);
@@ -160,37 +151,23 @@ public class FocusFinder {
            }
        }

        switch (directionMasked) {
        switch (direction) {
            case View.FOCUS_FORWARD:
            case View.FOCUS_BACKWARD:
                return findNextInputFocusInRelativeDirection(focusables, root, focused, focusedRect,
                        directionMasked);
                return findNextFocusInRelativeDirection(focusables, root, focused, focusedRect,
                        direction);
            case View.FOCUS_UP:
            case View.FOCUS_DOWN:
            case View.FOCUS_LEFT:
            case View.FOCUS_RIGHT:
                return findNextInputFocusInAbsoluteDirection(focusables, root, focused,
                        focusedRect, directionMasked);
                return findNextFocusInAbsoluteDirection(focusables, root, focused,
                        focusedRect, direction);
            default:
                throw new IllegalArgumentException("Unknown direction: " + directionMasked);
        }
    }

    private View findNextAccessibilityFocus(ViewGroup root, View focused,
            Rect focusedRect, int direction) {
        ArrayList<View> focusables = mTempList;
        try {
            focusables.clear();
            root.addFocusables(focusables, direction, View.FOCUSABLES_ACCESSIBILITY);
            View next = findNextFocus(root, focused, focusedRect, direction,
                    focusables);
            return next;
        } finally {
            focusables.clear();
                throw new IllegalArgumentException("Unknown direction: " + direction);
        }
    }

    private View findNextInputFocusInRelativeDirection(ArrayList<View> focusables, ViewGroup root,
    private View findNextFocusInRelativeDirection(ArrayList<View> focusables, ViewGroup root,
            View focused, Rect focusedRect, int direction) {
        try {
            // Note: This sort is stable.
@@ -222,7 +199,7 @@ public class FocusFinder {
        focusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
    }

    View findNextInputFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused,
    View findNextFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused,
            Rect focusedRect, int direction) {
        // initialize the best candidate to something impossible
        // (so the first plausible view will become the best choice)
+4 −231
Original line number Diff line number Diff line
@@ -1006,14 +1006,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
    /**
     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
     * should add only accessibility focusable Views.
     *
     * @hide
     */
    public static final int FOCUSABLES_ACCESSIBILITY = 0x00000002;
    /**
     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
     * item.
@@ -1046,58 +1038,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public static final int FOCUS_DOWN = 0x00000082;
    // Accessibility focus directions.
    /**
     * The accessibility focus which is the current user position when
     * interacting with the accessibility framework.
     *
     * @hide
     */
    public static final int FOCUS_ACCESSIBILITY =  0x00001000;
    /**
     * Use with {@link #focusSearch(int)}. Move acessibility focus left.
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUS_LEFT = FOCUS_LEFT | FOCUS_ACCESSIBILITY;
    /**
     * Use with {@link #focusSearch(int)}. Move acessibility focus up.
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUS_UP = FOCUS_UP | FOCUS_ACCESSIBILITY;
    /**
     * Use with {@link #focusSearch(int)}. Move acessibility focus right.
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUS_RIGHT = FOCUS_RIGHT | FOCUS_ACCESSIBILITY;
    /**
     * Use with {@link #focusSearch(int)}. Move acessibility focus down.
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUS_DOWN = FOCUS_DOWN | FOCUS_ACCESSIBILITY;
    /**
     * Use with {@link #focusSearch(int)}. Move acessibility focus forward.
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUS_FORWARD = FOCUS_FORWARD | FOCUS_ACCESSIBILITY;
    /**
     * Use with {@link #focusSearch(int)}. Move acessibility focus backward.
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUS_BACKWARD = FOCUS_BACKWARD | FOCUS_ACCESSIBILITY;
    /**
     * Bits of {@link #getMeasuredWidthAndState()} and
     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
@@ -2135,71 +2075,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    static final int VIEW_QUICK_REJECTED = 0x10000000;
    // Accessiblity constants for mPrivateFlags2
    /**
     * Shift for the bits in {@link #mPrivateFlags2} related to the
     * "accessibilityFocusable" attribute.
     */
    static final int ACCESSIBILITY_FOCUSABLE_SHIFT = 29;
    /**
     * The system determines whether the view can take accessibility focus - default (recommended).
     * <p>
     * Such a view is consideted by the focus search if it is:
     * <ul>
     * <li>
     * Important for accessibility and actionable (clickable, long clickable, focusable)
     * </li>
     * <li>
     * Important for accessibility, not actionable (clickable, long clickable, focusable),
     * and does not have an actionable predecessor.
     * </li>
     * </ul>
     * An accessibility srvice can request putting accessibility focus on such a view.
     * </p>
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUSABLE_AUTO = 0x00000000;
    /**
     * The view can take accessibility focus.
     * <p>
     * A view that can take accessibility focus is always considered during focus
     * search and an accessibility service can request putting accessibility focus
     * on it.
     * </p>
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUSABLE_YES = 0x00000001;
    /**
     * The view can not take accessibility focus.
     * <p>
     * A view that can not take accessibility focus is never considered during focus
     * search and an accessibility service can not request putting accessibility focus
     * on it.
     * </p>
     *
     * @hide
     */
    public static final int ACCESSIBILITY_FOCUSABLE_NO = 0x00000002;
    /**
     * The default whether the view is accessiblity focusable.
     */
    static final int ACCESSIBILITY_FOCUSABLE_DEFAULT = ACCESSIBILITY_FOCUSABLE_AUTO;
    /**
     * Mask for obtainig the bits which specifies how to determine
     * whether a view is accessibility focusable.
     */
    static final int ACCESSIBILITY_FOCUSABLE_MASK = (ACCESSIBILITY_FOCUSABLE_AUTO
        | ACCESSIBILITY_FOCUSABLE_YES | ACCESSIBILITY_FOCUSABLE_NO)
        << ACCESSIBILITY_FOCUSABLE_SHIFT;
    // There are a couple of flags left in mPrivateFlags2
    /* End of masks for mPrivateFlags2 */
@@ -3216,8 +3092,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
                (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
                (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT) |
                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT) |
                (ACCESSIBILITY_FOCUSABLE_DEFAULT << ACCESSIBILITY_FOCUSABLE_SHIFT);
                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
        mUserPaddingStart = -1;
@@ -4860,10 +4735,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
        if (!isAccessibilityFocused()) {
            final int mode = getAccessibilityFocusable();
            if (mode == ACCESSIBILITY_FOCUSABLE_YES || mode == ACCESSIBILITY_FOCUSABLE_AUTO) {
            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
            }
        } else {
            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
        }
@@ -6166,12 +6038,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (views == null) {
            return;
        }
        if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
            if (isAccessibilityFocusable()) {
                views.add(this);
                return;
            }
        }
        if (!isFocusable()) {
            return;
        }
@@ -6336,29 +6202,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
    }
    private void requestAccessibilityFocusFromHover() {
        if (includeForAccessibility() && isActionableForAccessibility()) {
            requestAccessibilityFocus();
        } else {
            if (mParent != null) {
                View nextFocus = mParent.findViewToTakeAccessibilityFocusFromHover(this, this);
                if (nextFocus != null) {
                    nextFocus.requestAccessibilityFocus();
                }
            }
        }
    }
    private boolean canTakeAccessibilityFocusFromHover() {
        if (includeForAccessibility() && isActionableForAccessibility()) {
            return true;
        }
        if (mParent != null) {
            return (mParent.findViewToTakeAccessibilityFocusFromHover(this, this) == this);
        }
        return false;
    }
    /**
     * Clears accessibility focus without calling any callback methods
     * normally invoked in {@link #clearAccessibilityFocus()}. This method
@@ -6573,73 +6416,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
    }
    /**
     * Gets the mode for determining whether this View can take accessibility focus.
     *
     * @return The mode for determining whether a View can take accessibility focus.
     *
     * @attr ref android.R.styleable#View_accessibilityFocusable
     *
     * @see #ACCESSIBILITY_FOCUSABLE_YES
     * @see #ACCESSIBILITY_FOCUSABLE_NO
     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
     *
     * @hide
     */
    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_AUTO, to = "auto"),
            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_YES, to = "yes"),
            @ViewDebug.IntToString(from = ACCESSIBILITY_FOCUSABLE_NO, to = "no")
        })
    public int getAccessibilityFocusable() {
        return (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK) >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
    }
    /**
     * Sets how to determine whether this view can take accessibility focus.
     *
     * @param mode How to determine whether this view can take accessibility focus.
     *
     * @attr ref android.R.styleable#View_accessibilityFocusable
     *
     * @see #ACCESSIBILITY_FOCUSABLE_YES
     * @see #ACCESSIBILITY_FOCUSABLE_NO
     * @see #ACCESSIBILITY_FOCUSABLE_AUTO
     *
     * @hide
     */
    public void setAccessibilityFocusable(int mode) {
        if (mode != getAccessibilityFocusable()) {
            mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSABLE_MASK;
            mPrivateFlags2 |= (mode << ACCESSIBILITY_FOCUSABLE_SHIFT)
                    & ACCESSIBILITY_FOCUSABLE_MASK;
            notifyAccessibilityStateChanged();
        }
    }
    /**
     * Gets whether this view can take accessibility focus.
     *
     * @return Whether the view can take accessibility focus.
     *
     * @hide
     */
    public boolean isAccessibilityFocusable() {
        final int mode = (mPrivateFlags2 & ACCESSIBILITY_FOCUSABLE_MASK)
                >>> ACCESSIBILITY_FOCUSABLE_SHIFT;
        switch (mode) {
            case ACCESSIBILITY_FOCUSABLE_YES:
                return true;
            case ACCESSIBILITY_FOCUSABLE_NO:
                return false;
            case ACCESSIBILITY_FOCUSABLE_AUTO:
                return canTakeAccessibilityFocusFromHover()
                        || getAccessibilityNodeProvider() != null;
            default:
                throw new IllegalArgumentException("Unknow accessibility focusable mode: " + mode);
        }
    }
    /**
     * Gets the parent for accessibility purposes. Note that the parent for
     * accessibility is not necessary the immediate parent. It is the first
@@ -6821,10 +6597,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                }
            } break;
            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
                final int mode = getAccessibilityFocusable();
                if (!isAccessibilityFocused()
                        && (mode == ACCESSIBILITY_FOCUSABLE_YES
                                || mode == ACCESSIBILITY_FOCUSABLE_AUTO)) {
                if (!isAccessibilityFocused()) {
                    return requestAccessibilityFocus();
                }
            } break;
+3 −24
Original line number Diff line number Diff line
@@ -624,11 +624,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
     *        FOCUS_RIGHT, or 0 for not applicable.
     */
    public View focusSearch(View focused, int direction) {
        // If we are moving accessibility focus we want to consider all
        // views no matter if they are on the screen. It is responsibility
        // of the accessibility service to check whether the result is in
        // the screen.
        if (isRootNamespace() && (direction & FOCUS_ACCESSIBILITY) == 0) {
        if (isRootNamespace()) {
            // root namespace means we should consider ourselves the top of the
            // tree for focus searching; otherwise we could be focus searching
            // into other tabs.  see LocalActivityManager and TabHost for more info
@@ -863,8 +859,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager

        final int descendantFocusability = getDescendantFocusability();

        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS
                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
            final int count = mChildrenCount;
            final View[] children = mChildren;

@@ -882,9 +877,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        // among the focusable children would be more interesting.
        if (descendantFocusability != FOCUS_AFTER_DESCENDANTS
                // No focusable descendants
                || (focusableCount == views.size())
                // We are collecting accessibility focusables.
                || (focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
                || (focusableCount == views.size())) {
            super.addFocusables(views, direction, focusableMode);
        }
    }
@@ -1653,20 +1646,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }
    }

    /**
     * @hide
     */
    @Override
    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
        if (includeForAccessibility() && isActionableForAccessibility()) {
            return this;
        }
        if (mParent != null) {
            return mParent.findViewToTakeAccessibilityFocusFromHover(this, descendant);
        }
        return null;
    }

    /**
     * Implement this method to intercept hover events before they are handled
     * by child views.
+0 −12
Original line number Diff line number Diff line
@@ -295,16 +295,4 @@ public interface ViewParent {
     * @hide
     */
    public void childAccessibilityStateChanged(View child);

    /**
     * A descendant requests this view to find a candidate to take accessibility
     * focus from hover.
     *
     * @param child The child making the call.
     * @param descendant The descendant that made the initial request.
     * @return A view to take accessibility focus.
     *
     * @hide
     */
    public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant);
}
Loading