Loading api/current.txt +7 −0 Original line number Diff line number Diff line Loading @@ -26352,21 +26352,28 @@ package android.view.accessibility { method public void setVisibleToUser(boolean); method public void writeToParcel(android.os.Parcel, int); 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_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_FOCUS = 2; // 0x2 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_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_LONG_CLICK = 32; // 0x20 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_PASTE = 32768; // 0x8000 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_SCROLL_BACKWARD = 8192; // 0x2000 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_SET_SELECTION = 131072; // 0x20000 field public static final android.os.Parcelable.Creator CREATOR; field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2 field public static final int FOCUS_INPUT = 1; // 0x1 core/java/android/view/View.java +57 −24 Original line number Diff line number Diff line Loading @@ -1562,9 +1562,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ int mAccessibilityViewId = NO_ID; /** * @hide */ private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; /** Loading Loading @@ -2516,8 +2513,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * 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. Loading Loading @@ -7009,21 +7008,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (arguments != null) { final int granularity = arguments.getInt( 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; case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { if (arguments != null) { final int granularity = arguments.getInt( 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; } return false; } private boolean nextAtGranularity(int granularity) { private boolean nextAtGranularity(int granularity, boolean extendSelection) { CharSequence text = getIterableTextForAccessibility(); if (text == null || text.length() == 0) { return false; Loading @@ -7032,21 +7035,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (iterator == null) { return false; } final int current = getAccessibilityCursorPosition(); int current = getAccessibilitySelectionEnd(); if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { current = 0; } final int[] range = iterator.following(current); if (range == null) { return false; } final int start = range[0]; 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( AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, granularity, start, end); return true; } private boolean previousAtGranularity(int granularity) { private boolean previousAtGranularity(int granularity, boolean extendSelection) { CharSequence text = getIterableTextForAccessibility(); if (text == null || text.length() == 0) { return false; Loading @@ -7055,15 +7069,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (iterator == null) { return false; } int current = getAccessibilityCursorPosition(); int current = getAccessibilitySelectionStart(); if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 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); if (range == null) { Loading @@ -7071,11 +7079,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } final int start = range[0]; final int end = range[1]; // Always put the cursor after the character to ease edit. if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) { setAccessibilityCursorPosition(end); if (extendSelection && isAccessibilitySelectionExtendable()) { int selectionEnd = getAccessibilitySelectionEnd(); if (selectionEnd == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { selectionEnd = end; } setAccessibilitySelection(start, selectionEnd); } else { setAccessibilityCursorPosition(start); setAccessibilitySelection(start, start); } sendViewTextTraversedAtGranularityEvent( AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, Loading @@ -7094,18 +7105,40 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return getContentDescription(); } /** * Gets whether accessibility selection can be extended. * * @return If selection is extensible. * * @hide */ public boolean isAccessibilitySelectionExtendable() { return false; } /** * @hide */ public int getAccessibilityCursorPosition() { public int getAccessibilitySelectionStart() { return mAccessibilityCursorPosition; } /** * @hide */ public void setAccessibilityCursorPosition(int position) { mAccessibilityCursorPosition = position; public int getAccessibilitySelectionEnd() { 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, Loading core/java/android/view/accessibility/AccessibilityNodeInfo.java +98 −6 Original line number Diff line number Diff line Loading @@ -131,16 +131,22 @@ public class AccessibilityNodeInfo implements Parcelable { * at a given movement granularity. For example, move to the next character, * word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> * <strong>Example:</strong> Move to the previous character and do not extend selection. * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, * false); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments); * </code></pre></p> * </p> * * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN * * @see #setMovementGranularities(int) * @see #getMovementGranularities() * Loading @@ -157,17 +163,23 @@ public class AccessibilityNodeInfo implements Parcelable { * at a given movement granularity. For example, move to the next character, * word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> * <strong>Example:</strong> Move to the next character and do not extend selection. * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, * false); * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, * arguments); * </code></pre></p> * </p> * * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN * * @see #setMovementGranularities(int) * @see #getMovementGranularities() * Loading Loading @@ -219,6 +231,41 @@ public class AccessibilityNodeInfo implements Parcelable { */ 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. * <p> Loading @@ -226,6 +273,9 @@ public class AccessibilityNodeInfo implements Parcelable { * <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_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT"; Loading @@ -237,10 +287,52 @@ public class AccessibilityNodeInfo implements Parcelable { * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT}, * {@link #ACTION_PREVIOUS_HTML_ELEMENT} * </p> * * @see #ACTION_NEXT_HTML_ELEMENT * @see #ACTION_PREVIOUS_HTML_ELEMENT */ public static final 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. */ Loading core/java/android/widget/TextView.java +104 −11 Original line number Diff line number Diff line Loading @@ -7985,6 +7985,80 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH | 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 Loading Loading @@ -8554,32 +8628,51 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ @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())) { final int selectionEnd = getSelectionEnd(); if (selectionEnd >= 0) { return selectionEnd; } } return super.getAccessibilityCursorPosition(); return ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; } /** * @hide */ @Override public void setAccessibilityCursorPosition(int index) { if (getAccessibilityCursorPosition() == index) { public void setAccessibilitySelection(int start, int end) { if (getAccessibilitySelectionStart() == start && getAccessibilitySelectionEnd() == end) { return; } if (TextUtils.isEmpty(getContentDescription())) { if (index >= 0 && index <= mText.length()) { Selection.setSelection((Spannable) mText, index); } else { Selection.removeSelection((Spannable) mText); } CharSequence text = getIterableTextForAccessibility(); if (start >= 0 && start <= end && end <= text.length()) { Selection.setSelection((Spannable) text, start, end); } else { super.setAccessibilityCursorPosition(index); Selection.removeSelection((Spannable) text); } } Loading services/java/com/android/server/accessibility/AccessibilityManagerService.java +5 −1 Original line number Diff line number Diff line Loading @@ -2225,7 +2225,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT | 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 = AccessibilityEvent.TYPE_VIEW_CLICKED Loading Loading
api/current.txt +7 −0 Original line number Diff line number Diff line Loading @@ -26352,21 +26352,28 @@ package android.view.accessibility { method public void setVisibleToUser(boolean); method public void writeToParcel(android.os.Parcel, int); 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_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_FOCUS = 2; // 0x2 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_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_LONG_CLICK = 32; // 0x20 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_PASTE = 32768; // 0x8000 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_SCROLL_BACKWARD = 8192; // 0x2000 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_SET_SELECTION = 131072; // 0x20000 field public static final android.os.Parcelable.Creator CREATOR; field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2 field public static final int FOCUS_INPUT = 1; // 0x1
core/java/android/view/View.java +57 −24 Original line number Diff line number Diff line Loading @@ -1562,9 +1562,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ int mAccessibilityViewId = NO_ID; /** * @hide */ private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; /** Loading Loading @@ -2516,8 +2513,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * 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. Loading Loading @@ -7009,21 +7008,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (arguments != null) { final int granularity = arguments.getInt( 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; case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { if (arguments != null) { final int granularity = arguments.getInt( 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; } return false; } private boolean nextAtGranularity(int granularity) { private boolean nextAtGranularity(int granularity, boolean extendSelection) { CharSequence text = getIterableTextForAccessibility(); if (text == null || text.length() == 0) { return false; Loading @@ -7032,21 +7035,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (iterator == null) { return false; } final int current = getAccessibilityCursorPosition(); int current = getAccessibilitySelectionEnd(); if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { current = 0; } final int[] range = iterator.following(current); if (range == null) { return false; } final int start = range[0]; 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( AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, granularity, start, end); return true; } private boolean previousAtGranularity(int granularity) { private boolean previousAtGranularity(int granularity, boolean extendSelection) { CharSequence text = getIterableTextForAccessibility(); if (text == null || text.length() == 0) { return false; Loading @@ -7055,15 +7069,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (iterator == null) { return false; } int current = getAccessibilityCursorPosition(); int current = getAccessibilitySelectionStart(); if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 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); if (range == null) { Loading @@ -7071,11 +7079,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } final int start = range[0]; final int end = range[1]; // Always put the cursor after the character to ease edit. if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) { setAccessibilityCursorPosition(end); if (extendSelection && isAccessibilitySelectionExtendable()) { int selectionEnd = getAccessibilitySelectionEnd(); if (selectionEnd == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { selectionEnd = end; } setAccessibilitySelection(start, selectionEnd); } else { setAccessibilityCursorPosition(start); setAccessibilitySelection(start, start); } sendViewTextTraversedAtGranularityEvent( AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, Loading @@ -7094,18 +7105,40 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return getContentDescription(); } /** * Gets whether accessibility selection can be extended. * * @return If selection is extensible. * * @hide */ public boolean isAccessibilitySelectionExtendable() { return false; } /** * @hide */ public int getAccessibilityCursorPosition() { public int getAccessibilitySelectionStart() { return mAccessibilityCursorPosition; } /** * @hide */ public void setAccessibilityCursorPosition(int position) { mAccessibilityCursorPosition = position; public int getAccessibilitySelectionEnd() { 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, Loading
core/java/android/view/accessibility/AccessibilityNodeInfo.java +98 −6 Original line number Diff line number Diff line Loading @@ -131,16 +131,22 @@ public class AccessibilityNodeInfo implements Parcelable { * at a given movement granularity. For example, move to the next character, * word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> * <strong>Example:</strong> Move to the previous character and do not extend selection. * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, * false); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments); * </code></pre></p> * </p> * * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN * * @see #setMovementGranularities(int) * @see #getMovementGranularities() * Loading @@ -157,17 +163,23 @@ public class AccessibilityNodeInfo implements Parcelable { * at a given movement granularity. For example, move to the next character, * word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<, * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br> * <strong>Example:</strong> Move to the next character and do not extend selection. * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, * false); * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, * arguments); * </code></pre></p> * </p> * * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN * * @see #setMovementGranularities(int) * @see #getMovementGranularities() * Loading Loading @@ -219,6 +231,41 @@ public class AccessibilityNodeInfo implements Parcelable { */ 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. * <p> Loading @@ -226,6 +273,9 @@ public class AccessibilityNodeInfo implements Parcelable { * <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_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT"; Loading @@ -237,10 +287,52 @@ public class AccessibilityNodeInfo implements Parcelable { * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT}, * {@link #ACTION_PREVIOUS_HTML_ELEMENT} * </p> * * @see #ACTION_NEXT_HTML_ELEMENT * @see #ACTION_PREVIOUS_HTML_ELEMENT */ public static final 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. */ Loading
core/java/android/widget/TextView.java +104 −11 Original line number Diff line number Diff line Loading @@ -7985,6 +7985,80 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH | 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 Loading Loading @@ -8554,32 +8628,51 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ @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())) { final int selectionEnd = getSelectionEnd(); if (selectionEnd >= 0) { return selectionEnd; } } return super.getAccessibilityCursorPosition(); return ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; } /** * @hide */ @Override public void setAccessibilityCursorPosition(int index) { if (getAccessibilityCursorPosition() == index) { public void setAccessibilitySelection(int start, int end) { if (getAccessibilitySelectionStart() == start && getAccessibilitySelectionEnd() == end) { return; } if (TextUtils.isEmpty(getContentDescription())) { if (index >= 0 && index <= mText.length()) { Selection.setSelection((Spannable) mText, index); } else { Selection.removeSelection((Spannable) mText); } CharSequence text = getIterableTextForAccessibility(); if (start >= 0 && start <= end && end <= text.length()) { Selection.setSelection((Spannable) text, start, end); } else { super.setAccessibilityCursorPosition(index); Selection.removeSelection((Spannable) text); } } Loading
services/java/com/android/server/accessibility/AccessibilityManagerService.java +5 −1 Original line number Diff line number Diff line Loading @@ -2225,7 +2225,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT | 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 = AccessibilityEvent.TYPE_VIEW_CLICKED Loading