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

Commit f48a2d30 authored by Svetoslav's avatar Svetoslav Committed by Android (Google) Code Review
Browse files

Merge "Add accessibility actions for text editing."

parents ec695824 7c51284d
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -26352,21 +26352,28 @@ package android.view.accessibility {
    method public void setVisibleToUser(boolean);
    method public void setVisibleToUser(boolean);
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
    field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
    field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
    field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
    field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
    field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
    field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
    field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
    field public static final java.lang.String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
    field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
    field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
    field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
    field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
    field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
    field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
    field public static final int ACTION_CLICK = 16; // 0x10
    field public static final int ACTION_CLICK = 16; // 0x10
    field public static final int ACTION_COPY = 16384; // 0x4000
    field public static final int ACTION_CUT = 65536; // 0x10000
    field public static final int ACTION_FOCUS = 1; // 0x1
    field public static final int ACTION_FOCUS = 1; // 0x1
    field public static final int ACTION_LONG_CLICK = 32; // 0x20
    field public static final int ACTION_LONG_CLICK = 32; // 0x20
    field public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 256; // 0x100
    field public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 256; // 0x100
    field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400
    field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400
    field public static final int ACTION_PASTE = 32768; // 0x8000
    field public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 512; // 0x200
    field public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 512; // 0x200
    field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800
    field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800
    field public static final int ACTION_SCROLL_BACKWARD = 8192; // 0x2000
    field public static final int ACTION_SCROLL_BACKWARD = 8192; // 0x2000
    field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000
    field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000
    field public static final int ACTION_SELECT = 4; // 0x4
    field public static final int ACTION_SELECT = 4; // 0x4
    field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
    field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
    field public static final int FOCUS_INPUT = 1; // 0x1
    field public static final int FOCUS_INPUT = 1; // 0x1
+57 −24
Original line number Original line Diff line number Diff line
@@ -1562,9 +1562,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
     */
    int mAccessibilityViewId = NO_ID;
    int mAccessibilityViewId = NO_ID;
    /**
     * @hide
     */
    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
    /**
    /**
@@ -2516,8 +2513,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    /**
    /**
     * The undefined cursor position.
     * The undefined cursor position.
     *
     * @hide
     */
     */
    private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
    /**
    /**
     * Indicates that the screen has changed state and is now off.
     * Indicates that the screen has changed state and is now off.
@@ -7009,21 +7008,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                if (arguments != null) {
                if (arguments != null) {
                    final int granularity = arguments.getInt(
                    final int granularity = arguments.getInt(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                    return nextAtGranularity(granularity);
                    final boolean extendSelection = arguments.getBoolean(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
                    return nextAtGranularity(granularity, extendSelection);
                }
                }
            } break;
            } break;
            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
                if (arguments != null) {
                if (arguments != null) {
                    final int granularity = arguments.getInt(
                    final int granularity = arguments.getInt(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
                    return previousAtGranularity(granularity);
                    final boolean extendSelection = arguments.getBoolean(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
                    return previousAtGranularity(granularity, extendSelection);
                }
                }
            } break;
            } break;
        }
        }
        return false;
        return false;
    }
    }
    private boolean nextAtGranularity(int granularity) {
    private boolean nextAtGranularity(int granularity, boolean extendSelection) {
        CharSequence text = getIterableTextForAccessibility();
        CharSequence text = getIterableTextForAccessibility();
        if (text == null || text.length() == 0) {
        if (text == null || text.length() == 0) {
            return false;
            return false;
@@ -7032,21 +7035,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (iterator == null) {
        if (iterator == null) {
            return false;
            return false;
        }
        }
        final int current = getAccessibilityCursorPosition();
        int current = getAccessibilitySelectionEnd();
        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
            current = 0;
        }
        final int[] range = iterator.following(current);
        final int[] range = iterator.following(current);
        if (range == null) {
        if (range == null) {
            return false;
            return false;
        }
        }
        final int start = range[0];
        final int start = range[0];
        final int end = range[1];
        final int end = range[1];
        setAccessibilityCursorPosition(end);
        if (extendSelection && isAccessibilitySelectionExtendable()) {
            int selectionStart = getAccessibilitySelectionStart();
            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
                selectionStart = start;
            }
            setAccessibilitySelection(selectionStart, end);
        } else {
            setAccessibilitySelection(end, end);
        }
        sendViewTextTraversedAtGranularityEvent(
        sendViewTextTraversedAtGranularityEvent(
                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
                granularity, start, end);
                granularity, start, end);
        return true;
        return true;
    }
    }
    private boolean previousAtGranularity(int granularity) {
    private boolean previousAtGranularity(int granularity, boolean extendSelection) {
        CharSequence text = getIterableTextForAccessibility();
        CharSequence text = getIterableTextForAccessibility();
        if (text == null || text.length() == 0) {
        if (text == null || text.length() == 0) {
            return false;
            return false;
@@ -7055,15 +7069,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (iterator == null) {
        if (iterator == null) {
            return false;
            return false;
        }
        }
        int current = getAccessibilityCursorPosition();
        int current = getAccessibilitySelectionStart();
        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
            current = text.length();
            current = text.length();
            setAccessibilityCursorPosition(current);
        } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
            // When traversing by character we always put the cursor after the character
            // to ease edit and have to compensate before asking the for previous segment.
            current--;
            setAccessibilityCursorPosition(current);
        }
        }
        final int[] range = iterator.preceding(current);
        final int[] range = iterator.preceding(current);
        if (range == null) {
        if (range == null) {
@@ -7071,11 +7079,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
        }
        final int start = range[0];
        final int start = range[0];
        final int end = range[1];
        final int end = range[1];
        // Always put the cursor after the character to ease edit.
        if (extendSelection && isAccessibilitySelectionExtendable()) {
        if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
            int selectionEnd = getAccessibilitySelectionEnd();
            setAccessibilityCursorPosition(end);
            if (selectionEnd == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
                selectionEnd = end;
            }
            setAccessibilitySelection(start, selectionEnd);
        } else {
        } else {
            setAccessibilityCursorPosition(start);
            setAccessibilitySelection(start, start);
        }
        }
        sendViewTextTraversedAtGranularityEvent(
        sendViewTextTraversedAtGranularityEvent(
                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
@@ -7094,18 +7105,40 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return getContentDescription();
        return getContentDescription();
    }
    }
    /**
     * Gets whether accessibility selection can be extended.
     *
     * @return If selection is extensible.
     *
     * @hide
     */
    public boolean isAccessibilitySelectionExtendable() {
        return false;
    }
    /**
    /**
     * @hide
     * @hide
     */
     */
    public int getAccessibilityCursorPosition() {
    public int getAccessibilitySelectionStart() {
        return mAccessibilityCursorPosition;
        return mAccessibilityCursorPosition;
    }
    }
    /**
    /**
     * @hide
     * @hide
     */
     */
    public void setAccessibilityCursorPosition(int position) {
    public int getAccessibilitySelectionEnd() {
        mAccessibilityCursorPosition = position;
        return getAccessibilitySelectionStart();
    }
    /**
     * @hide
     */
    public void setAccessibilitySelection(int start, int end) {
        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
            mAccessibilityCursorPosition = start;
        } else {
            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
        }
    }
    }
    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
+98 −6
Original line number Original line Diff line number Diff line
@@ -131,16 +131,22 @@ public class AccessibilityNodeInfo implements Parcelable {
     * at a given movement granularity. For example, move to the next character,
     * at a given movement granularity. For example, move to the next character,
     * word, etc.
     * word, etc.
     * <p>
     * <p>
     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br>
     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
     * <strong>Example:</strong>
     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
     * <strong>Example:</strong> Move to the previous character and do not extend selection.
     * <code><pre><p>
     * <code><pre><p>
     *   Bundle arguments = new Bundle();
     *   Bundle arguments = new Bundle();
     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
     *           false);
     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
     * </code></pre></p>
     * </code></pre></p>
     * </p>
     * </p>
     *
     *
     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
     *
     * @see #setMovementGranularities(int)
     * @see #setMovementGranularities(int)
     * @see #getMovementGranularities()
     * @see #getMovementGranularities()
     *
     *
@@ -157,17 +163,23 @@ public class AccessibilityNodeInfo implements Parcelable {
     * at a given movement granularity. For example, move to the next character,
     * at a given movement granularity. For example, move to the next character,
     * word, etc.
     * word, etc.
     * <p>
     * <p>
     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br>
     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
     * <strong>Example:</strong>
     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
     * <strong>Example:</strong> Move to the next character and do not extend selection.
     * <code><pre><p>
     * <code><pre><p>
     *   Bundle arguments = new Bundle();
     *   Bundle arguments = new Bundle();
     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
     *           false);
     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
     *           arguments);
     *           arguments);
     * </code></pre></p>
     * </code></pre></p>
     * </p>
     * </p>
     *
     *
     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
     *
     * @see #setMovementGranularities(int)
     * @see #setMovementGranularities(int)
     * @see #getMovementGranularities()
     * @see #getMovementGranularities()
     *
     *
@@ -219,6 +231,41 @@ public class AccessibilityNodeInfo implements Parcelable {
     */
     */
    public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
    public static final int ACTION_SCROLL_BACKWARD = 0x00002000;


    /**
     * Action to copy the current selection to the clipboard.
     */
    public static final int ACTION_COPY = 0x00004000;

    /**
     * Action to paste the current clipboard content.
     */
    public static final int ACTION_PASTE = 0x00008000;

    /**
     * Action to cut the current selection and place it to the clipboard.
     */
    public static final int ACTION_CUT = 0x00010000;

    /**
     * Action to set the selection. Performing this action with no arguments
     * clears the selection.
     * <p>
     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SELECTION_START_INT},
     * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
     * <strong>Example:</strong>
     * <code><pre><p>
     *   Bundle arguments = new Bundle();
     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
     *   info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
     * </code></pre></p>
     * </p>
     *
     * @see #ACTION_ARGUMENT_SELECTION_START_INT
     * @see #ACTION_ARGUMENT_SELECTION_END_INT
     */
    public static final int ACTION_SET_SELECTION = 0x00020000;

    /**
    /**
     * Argument for which movement granularity to be used when traversing the node text.
     * Argument for which movement granularity to be used when traversing the node text.
     * <p>
     * <p>
@@ -226,6 +273,9 @@ public class AccessibilityNodeInfo implements Parcelable {
     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
     * </p>
     * </p>
     *
     * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
     * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
     */
     */
    public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
    public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
            "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
            "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
@@ -237,10 +287,52 @@ public class AccessibilityNodeInfo implements Parcelable {
     * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
     * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
     *         {@link #ACTION_PREVIOUS_HTML_ELEMENT}
     *         {@link #ACTION_PREVIOUS_HTML_ELEMENT}
     * </p>
     * </p>
     *
     * @see #ACTION_NEXT_HTML_ELEMENT
     * @see #ACTION_PREVIOUS_HTML_ELEMENT
     */
     */
    public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
    public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
            "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
            "ACTION_ARGUMENT_HTML_ELEMENT_STRING";


    /**
     * Argument for whether when moving at granularity to extend the selection
     * or to move it otherwise.
     * <p>
     * <strong>Type:</strong> boolean<br>
     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
     * </p>
     *
     * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
     * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
     */
    public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
            "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";

    /**
     * Argument for specifying the selection start.
     * <p>
     * <strong>Type:</strong> int<br>
     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
     * </p>
     *
     * @see #ACTION_SET_SELECTION
     */
    public static final String ACTION_ARGUMENT_SELECTION_START_INT =
            "ACTION_ARGUMENT_SELECTION_START_INT";

    /**
     * Argument for specifying the selection end.
     * <p>
     * <strong>Type:</strong> int<br>
     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
     * </p>
     *
     * @see #ACTION_SET_SELECTION
     */
    public static final String ACTION_ARGUMENT_SELECTION_END_INT =
            "ACTION_ARGUMENT_SELECTION_END_INT";

    /**
    /**
     * The input focus.
     * The input focus.
     */
     */
+104 −11
Original line number Original line Diff line number Diff line
@@ -7985,6 +7985,80 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
        }
        }
        if (isFocused()) {
            if (canSelectText()) {
                info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
            }
            if (canCopy()) {
                info.addAction(AccessibilityNodeInfo.ACTION_COPY);
            }
            if (canPaste()) {
                info.addAction(AccessibilityNodeInfo.ACTION_PASTE);
            }
            if (canCut()) {
                info.addAction(AccessibilityNodeInfo.ACTION_CUT);
            }
        }
    }

    @Override
    public boolean performAccessibilityAction(int action, Bundle arguments) {
        switch (action) {
            case AccessibilityNodeInfo.ACTION_COPY: {
                if (isFocused() && canCopy()) {
                    if (onTextContextMenuItem(ID_COPY)) {
                        notifyAccessibilityStateChanged();
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_PASTE: {
                if (isFocused() && canPaste()) {
                    if (onTextContextMenuItem(ID_PASTE)) {
                        notifyAccessibilityStateChanged();
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_CUT: {
                if (isFocused() && canCut()) {
                    if (onTextContextMenuItem(ID_CUT)) {
                        notifyAccessibilityStateChanged();
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
                if (isFocused() && canSelectText()) {
                    final int start = (arguments != null) ? arguments.getInt(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
                    final int end = (arguments != null) ? arguments.getInt(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
                    CharSequence text = getIterableTextForAccessibility();
                    if (text == null) {
                        return false;
                    }
                    // No arguments clears the selection.
                    if (start == end && end == -1) {
                        Selection.removeSelection((Spannable) text);
                        notifyAccessibilityStateChanged();
                        return true;
                    }
                    if (start >= 0 && start <= end && end <= text.length()) {
                        Selection.setSelection((Spannable) text, start, end);
                        // Make sure selection mode is engaged.
                        if (mEditor != null) {
                            mEditor.startSelectionActionMode();
                        }
                        notifyAccessibilityStateChanged();
                        return true;
                    }
                }
            } return false;
            default: {
                return super.performAccessibilityAction(action, arguments);
            }
        }
    }
    }


    @Override
    @Override
@@ -8554,32 +8628,51 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     * @hide
     * @hide
     */
     */
    @Override
    @Override
    public int getAccessibilityCursorPosition() {
    public int getAccessibilitySelectionStart() {
        if (TextUtils.isEmpty(getContentDescription())) {
            final int selectionStart = getSelectionStart();
            if (selectionStart >= 0) {
                return selectionStart;
            }
        }
        return ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
    }

    /**
     * @hide
     */
    public boolean isAccessibilitySelectionExtendable() {
        return true;
    }

    /**
     * @hide
     */
    @Override
    public int getAccessibilitySelectionEnd() {
        if (TextUtils.isEmpty(getContentDescription())) {
        if (TextUtils.isEmpty(getContentDescription())) {
            final int selectionEnd = getSelectionEnd();
            final int selectionEnd = getSelectionEnd();
            if (selectionEnd >= 0) {
            if (selectionEnd >= 0) {
                return selectionEnd;
                return selectionEnd;
            }
            }
        }
        }
        return super.getAccessibilityCursorPosition();
        return ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
    }
    }


    /**
    /**
     * @hide
     * @hide
     */
     */
    @Override
    @Override
    public void setAccessibilityCursorPosition(int index) {
    public void setAccessibilitySelection(int start, int end) {
        if (getAccessibilityCursorPosition() == index) {
        if (getAccessibilitySelectionStart() == start
                && getAccessibilitySelectionEnd() == end) {
            return;
            return;
        }
        }
        if (TextUtils.isEmpty(getContentDescription())) {
        CharSequence text = getIterableTextForAccessibility();
            if (index >= 0 && index <= mText.length()) {
        if (start >= 0 && start <= end && end <= text.length()) {
                Selection.setSelection((Spannable) mText, index);
            Selection.setSelection((Spannable) text, start, end);
            } else {
                Selection.removeSelection((Spannable) mText);
            }
        } else {
        } else {
            super.setAccessibilityCursorPosition(index);
            Selection.removeSelection((Spannable) text);
        }
        }
    }
    }


+5 −1
Original line number Original line Diff line number Diff line
@@ -2225,7 +2225,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
            | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT
            | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT
            | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT
            | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT
            | AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
            | AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
            | AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD;
            | AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
            | AccessibilityNodeInfo.ACTION_COPY
            | AccessibilityNodeInfo.ACTION_PASTE
            | AccessibilityNodeInfo.ACTION_CUT
            | AccessibilityNodeInfo.ACTION_SET_SELECTION;


        private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
        private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
            AccessibilityEvent.TYPE_VIEW_CLICKED
            AccessibilityEvent.TYPE_VIEW_CLICKED