Loading api/current.txt +14 −3 Original line number Diff line number Diff line Loading @@ -24930,6 +24930,7 @@ package android.view.accessibility { method public static java.lang.String eventTypeToString(int); method public long getEventTime(); method public int getEventType(); method public int getGranularity(); method public java.lang.CharSequence getPackageName(); method public android.view.accessibility.AccessibilityRecord getRecord(int); method public int getRecordCount(); Loading @@ -24939,6 +24940,7 @@ package android.view.accessibility { method public static android.view.accessibility.AccessibilityEvent obtain(); method public void setEventTime(long); method public void setEventType(int); method public void setGranularity(int); method public void setPackageName(java.lang.CharSequence); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; Loading @@ -24960,6 +24962,7 @@ package android.view.accessibility { field public static final int TYPE_VIEW_SELECTED = 4; // 0x4 field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10 field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000 field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY = 131072; // 0x20000 field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800 field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20 } Loading Loading @@ -25000,7 +25003,7 @@ package android.view.accessibility { method public int getChildCount(); method public java.lang.CharSequence getClassName(); method public java.lang.CharSequence getContentDescription(); method public java.lang.CharSequence[] getGranularities(); method public int getGranularities(); method public java.lang.CharSequence getPackageName(); method public android.view.accessibility.AccessibilityNodeInfo getParent(); method public java.lang.CharSequence getText(); Loading Loading @@ -25034,7 +25037,7 @@ package android.view.accessibility { method public void setEnabled(boolean); method public void setFocusable(boolean); method public void setFocused(boolean); method public void setGranularities(java.lang.CharSequence[]); method public void setGranularities(int); method public void setLongClickable(boolean); method public void setPackageName(java.lang.CharSequence); method public void setParent(android.view.View); Loading @@ -25047,7 +25050,8 @@ package android.view.accessibility { method public void setText(java.lang.CharSequence); 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_GRANULARITY = "ACTION_ARGUMENT_GRANULARITY"; field public static final java.lang.String ACTION_ARGUMENT_GRANULARITY_INT = "ACTION_ARGUMENT_GRANULARITY_INT"; field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING"; 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 Loading @@ -25055,11 +25059,18 @@ package android.view.accessibility { 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_GRANULARITY = 256; // 0x100 field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400 field public static final int ACTION_PREVIOUS_AT_GRANULARITY = 512; // 0x200 field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800 field public static final int ACTION_SELECT = 4; // 0x4 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 field public static final int GRANULARITY_CHARACTER = 1; // 0x1 field public static final int GRANULARITY_LINE = 4; // 0x4 field public static final int GRANULARITY_PAGE = 16; // 0x10 field public static final int GRANULARITY_PARAGRAPH = 8; // 0x8 field public static final int GRANULARITY_WORD = 2; // 0x2 } public abstract class AccessibilityNodeProvider { core/java/android/view/accessibility/AccessibilityEvent.java +52 −0 Original line number Diff line number Diff line Loading @@ -226,6 +226,23 @@ import java.util.List; * <li>{@link #getContentDescription()} - The content description of the source.</li> * </ul> * </p> * <b>View text traversed at granularity</b> - represents the event of traversing the * text of a view at a given granularity. For example, moving to the next word.</br> * <em>Type:</em> {@link #TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY} </br> * <em>Properties:</em></br> * <ul> * <li>{@link #getEventType()} - The type of the event.</li> * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> * <li>{@link #getText()} - The text of the current text at the granularity.</li> * <li>{@link #isPassword()} - Whether the source is password.</li> * <li>{@link #isEnabled()} - Whether the source is enabled.</li> * <li>{@link #getContentDescription()} - The content description of the source.</li> * <li>{@link #getGranularity()} - Sets the granularity at which a view's text was traversed.</li> * </ul> * </p> * <p> * <b>View scrolled</b> - represents the event of scrolling a view. If * the source is a descendant of {@link android.widget.AdapterView} the Loading Loading @@ -579,6 +596,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par */ public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000; /** * Represents the event of traversing the text of a view at a given granularity. */ public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY = 0x00020000; /** * Mask for {@link AccessibilityEvent} all types. * Loading @@ -597,6 +619,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * @see #TYPE_VIEW_SCROLLED * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED * @see #TYPE_ANNOUNCEMENT * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY */ public static final int TYPES_ALL_MASK = 0xFFFFFFFF; Loading @@ -610,6 +633,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par private int mEventType; private CharSequence mPackageName; private long mEventTime; int mGranularity; private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>(); Loading @@ -627,6 +651,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par void init(AccessibilityEvent event) { super.init(event); mEventType = event.mEventType; mGranularity = event.mGranularity; mEventTime = event.mEventTime; mPackageName = event.mPackageName; } Loading Loading @@ -743,6 +768,27 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par mPackageName = packageName; } /** * Sets the text granularity that was traversed. * * @param granularity The granularity. * * @throws IllegalStateException If called from an AccessibilityService. */ public void setGranularity(int granularity) { enforceNotSealed(); mGranularity = granularity; } /** * Gets the text granularity that was traversed. * * @return The granularity. */ public int getGranularity() { return mGranularity; } /** * Returns a cached instance if such is available or a new one is * instantiated with its type property set. Loading Loading @@ -831,6 +877,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par protected void clear() { super.clear(); mEventType = 0; mGranularity = 0; mPackageName = null; mEventTime = 0; while (!mRecords.isEmpty()) { Loading @@ -847,6 +894,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par public void initFromParcel(Parcel parcel) { mSealed = (parcel.readInt() == 1); mEventType = parcel.readInt(); mGranularity = parcel.readInt(); mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); mEventTime = parcel.readLong(); mConnectionId = parcel.readInt(); Loading Loading @@ -897,6 +945,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(isSealed() ? 1 : 0); parcel.writeInt(mEventType); parcel.writeInt(mGranularity); TextUtils.writeToParcel(mPackageName, parcel, 0); parcel.writeLong(mEventTime); parcel.writeInt(mConnectionId); Loading Loading @@ -953,6 +1002,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par builder.append("EventType: ").append(eventTypeToString(mEventType)); builder.append("; EventTime: ").append(mEventTime); builder.append("; PackageName: ").append(mPackageName); builder.append("; Granularity: ").append(mGranularity); builder.append(super.toString()); if (DEBUG) { builder.append("\n"); Loading Loading @@ -1033,6 +1083,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par return "TYPE_VIEW_ACCESSIBILITY_FOCUSED"; case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED"; case TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY: return "TYPE_CURRENT_AT_GRANULARITY_CHANGED"; default: return null; } Loading core/java/android/view/accessibility/AccessibilityNodeInfo.java +142 −65 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ public class AccessibilityNodeInfo implements Parcelable { public static final int ACTION_CLEAR_SELECTION = 0x00000008; /** * Action that clicks on the node info. * Action that long clicks on the node info. */ public static final int ACTION_CLICK = 0x00000010; Loading @@ -122,78 +122,105 @@ public class AccessibilityNodeInfo implements Parcelable { public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080; /** * Action that requests from the node to go to the next entity in its content * at a given granularity. For example, move to the next word, link, etc. * <p> * <strong>Arguments:</strong> * <ul> * <li> * {@link #ACTION_ARGUMENT_GRANULARITY} * </li> * <li> * </p> * Action that requests to go to the next entity in this node's text * at a given granularity. For example, move to the next character, word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <code><pre><p> * // Assume the first granularity was presented to the user and she is * // making an explicit action to traverse the node at that granularity. * CharSequence granularity = info.getGranularity(0); * Bundle arguments = new Bundle(); * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY, granularity); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT, * AccessibilityNodeInfo.GRANULARITY_CHARACTER); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY, arguments); * </code></pre></p> * </li> * </ul> * </p> * @see #setGranularities(CharSequence[]) * * @see #setGranularities(int) * @see #getGranularities() * * @see #GRANULARITY_CHARACTER * @see #GRANULARITY_WORD * @see #GRANULARITY_LINE * @see #GRANULARITY_PARAGRAPH * @see #GRANULARITY_PAGE */ public static final int ACTION_NEXT_AT_GRANULARITY = 0x00000100; /** * Action that requests from the node to go to the previous entity in its content * at a given granularity. For example, move to the next word, link, etc. * <p> * <strong>Arguments:</strong> * <ul> * <li> * {@link #ACTION_ARGUMENT_GRANULARITY} * </li> * <li> * </p> * Action that requests to go to the previous entity in this node's text * at a given granularity. For example, move to the next character, word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <code><pre><p> * // Assume the first granularity was presented to the user and she is * // making an explicit action to traverse the node at that granularity. * CharSequence granularity = info.getGranularity(0); * Bundle arguments = new Bundle(); * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY, granularity); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY, arguments); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT, * AccessibilityNodeInfo.GRANULARITY_CHARACTER); * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY, arguments); * </code></pre></p> * </li> * </ul> * </p> * @see #setGranularities(CharSequence[]) * * @see #setGranularities(int) * @see #getGranularities() * * @see #GRANULARITY_CHARACTER * @see #GRANULARITY_WORD * @see #GRANULARITY_LINE * @see #GRANULARITY_PARAGRAPH * @see #GRANULARITY_PAGE */ public static final int ACTION_PREVIOUS_AT_GRANULARITY = 0x00000200; /** * Argument for which content granularity to be used when traversing the node content. * Action to move to the next HTML element of a given type. For example, move * to the BUTTON, INPUT, TABLE, etc. * <p> * <strong>Actions:</strong> * <ul> * <li> * {@link #ACTION_PREVIOUS_AT_GRANULARITY} * </li> * <li> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> * <strong>Example:</strong> * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments); * </code></pre></p> * </p> */ public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400; /** * Action to move to the previous HTML element of a given type. For example, move * to the BUTTON, INPUT, TABLE, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> * <strong>Example:</strong> * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments); * </code></pre></p> * </p> */ public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800; /** * Argument for which text granularity to be used when traversing the node text. * <p> * <strong>Type:</strong> int<br> * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_GRANULARITY}, * {@link #ACTION_PREVIOUS_AT_GRANULARITY} * </li> * </ul> * </p> */ public static final String ACTION_ARGUMENT_GRANULARITY = "ACTION_ARGUMENT_GRANULARITY"; public static final String ACTION_ARGUMENT_GRANULARITY_INT = "ACTION_ARGUMENT_GRANULARITY_INT"; /** * Argument for which HTML element to get moving to the next/previous HTML element. * <p> * <strong>Type:</strong> String<br> * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT}, * {@link #ACTION_PREVIOUS_HTML_ELEMENT} * </p> */ public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING"; /** * The input focus. Loading @@ -205,6 +232,33 @@ public class AccessibilityNodeInfo implements Parcelable { */ public static final int FOCUS_ACCESSIBILITY = 2; // Granularities /** * Granularity bit for traversing the text of a node by character. */ public static final int GRANULARITY_CHARACTER = 0x00000001; /** * Granularity bit for traversing the text of a node by word. */ public static final int GRANULARITY_WORD = 0x00000002; /** * Granularity bit for traversing the text of a node by line. */ public static final int GRANULARITY_LINE = 0x00000004; /** * Granularity bit for traversing the text of a node by paragraph. */ public static final int GRANULARITY_PARAGRAPH = 0x00000008; /** * Granularity bit for traversing the text of a node by page. */ public static final int GRANULARITY_PAGE = 0x00000010; // Boolean attributes. private static final int PROPERTY_CHECKABLE = 0x00000001; Loading Loading @@ -308,7 +362,7 @@ public class AccessibilityNodeInfo implements Parcelable { private final SparseLongArray mChildNodeIds = new SparseLongArray(); private int mActions; private CharSequence[] mGranularities; private int mGranularities; private int mConnectionId = UNDEFINED; Loading Loading @@ -532,28 +586,28 @@ public class AccessibilityNodeInfo implements Parcelable { } /** * Sets the granularities for traversing the content of this node. * Sets the text granularities for traversing the text of this node. * <p> * <strong>Note:</strong> Cannot be called from an * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> * * @param granularities The granularity names. * @param granularities The bit mask with granularities. * * @throws IllegalStateException If called from an AccessibilityService. */ public void setGranularities(CharSequence[] granularities) { public void setGranularities(int granularities) { enforceNotSealed(); mGranularities = granularities; } /** * Gets the granularities for traversing the content of this node. * Gets the granularities for traversing the text of this node. * * @return The count. * @return The bit mask with granularities. */ public CharSequence[] getGranularities() { public int getGranularities() { return mGranularities; } Loading Loading @@ -1339,8 +1393,6 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeLong(mParentNodeId); parcel.writeInt(mConnectionId); parcel.writeCharSequenceArray(mGranularities); SparseLongArray childIds = mChildNodeIds; final int childIdsSize = childIds.size(); parcel.writeInt(childIdsSize); Loading @@ -1360,6 +1412,8 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeInt(mActions); parcel.writeInt(mGranularities); parcel.writeInt(mBooleanProperties); parcel.writeCharSequence(mPackageName); Loading Loading @@ -1392,7 +1446,7 @@ public class AccessibilityNodeInfo implements Parcelable { mContentDescription = other.mContentDescription; mActions= other.mActions; mBooleanProperties = other.mBooleanProperties; mGranularities = (other.mGranularities) != null ? other.mGranularities.clone() : null; mGranularities = other.mGranularities; final int otherChildIdCount = other.mChildNodeIds.size(); for (int i = 0; i < otherChildIdCount; i++) { mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i)); Loading @@ -1411,8 +1465,6 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = parcel.readLong(); mConnectionId = parcel.readInt(); mGranularities = parcel.readCharSequenceArray(); SparseLongArray childIds = mChildNodeIds; final int childrenSize = parcel.readInt(); for (int i = 0; i < childrenSize; i++) { Loading @@ -1432,6 +1484,8 @@ public class AccessibilityNodeInfo implements Parcelable { mActions = parcel.readInt(); mGranularities = parcel.readInt(); mBooleanProperties = parcel.readInt(); mPackageName = parcel.readCharSequence(); Loading @@ -1449,7 +1503,7 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = ROOT_NODE_ID; mWindowId = UNDEFINED; mConnectionId = UNDEFINED; mGranularities = null; mGranularities = 0; mChildNodeIds.clear(); mBoundsInParent.set(0, 0, 0, 0); mBoundsInScreen.set(0, 0, 0, 0); Loading Loading @@ -1482,6 +1536,29 @@ public class AccessibilityNodeInfo implements Parcelable { } } /** * Gets the human readable granularity symbolic name. * * @param granularity The action. * @return The symbolic name. */ private static String getGranularitySymbolicName(int granularity) { switch (granularity) { case GRANULARITY_CHARACTER: return "GRANULARITY_CHARACTER"; case GRANULARITY_WORD: return "GRANULARITY_WORD"; case GRANULARITY_LINE: return "GRANULARITY_LINE"; case GRANULARITY_PARAGRAPH: return "GRANULARITY_PARAGRAPH"; case GRANULARITY_PAGE: return "GRANULARITY_PAGE"; default: throw new IllegalArgumentException("Unknown granularity: " + granularity); } } private boolean canPerformRequestOverConnection(long accessibilityNodeId) { return (mWindowId != UNDEFINED && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED Loading Loading @@ -1529,11 +1606,13 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId)); builder.append("; mParentNodeId: " + mParentNodeId); CharSequence[] granularities = mGranularities; int granularities = mGranularities; builder.append("; granularities: ["); for (int i = 0, count = granularities.length; i < count; i++) { builder.append(granularities[i]); if (i < count - 1) { while (granularities != 0) { final int granularity = 1 << Integer.numberOfTrailingZeros(granularities); granularities &= ~granularity; builder.append(getGranularitySymbolicName(granularity)); if (granularities != 0) { builder.append(", "); } } Loading Loading @@ -1570,7 +1649,6 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; scrollable: " + isScrollable()); builder.append("; ["); for (int actionBits = mActions; actionBits != 0;) { final int action = 1 << Integer.numberOfTrailingZeros(actionBits); actionBits &= ~action; Loading @@ -1579,7 +1657,6 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append(", "); } } builder.append("]"); return builder.toString(); Loading services/java/com/android/server/accessibility/AccessibilityManagerService.java +38 −4 Original line number Diff line number Diff line Loading @@ -1554,7 +1554,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub IAccessibilityInteractionConnection connection = null; synchronized (mLock) { final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this, resolvedWindowId, action); resolvedWindowId, action, arguments); if (!permissionGranted) { return false; } else { Loading Loading @@ -1702,7 +1702,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub | AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS | AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY; | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT; private static final int VALID_GRANULARITIES = AccessibilityNodeInfo.GRANULARITY_CHARACTER | AccessibilityNodeInfo.GRANULARITY_WORD | AccessibilityNodeInfo.GRANULARITY_LINE | AccessibilityNodeInfo.GRANULARITY_PARAGRAPH | AccessibilityNodeInfo.GRANULARITY_PAGE; private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = AccessibilityEvent.TYPE_VIEW_CLICKED Loading Loading @@ -1752,10 +1761,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId); } public boolean canPerformActionLocked(Service service, int windowId, int action) { public boolean canPerformActionLocked(Service service, int windowId, int action, Bundle arguments) { return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId) && isActionPermitted(action); && isActionPermitted(action) && isActionArgumentsValid(action, arguments); } public boolean canRetrieveWindowContent(Service service) { Loading @@ -1779,6 +1790,29 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return (VALID_ACTIONS & action) != 0; } private boolean isActionArgumentsValid(int action, Bundle arguments) { switch (action) { case AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY: case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY: { if (arguments.size() == 1) { final int granularity = arguments.getInt( AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT); return (granularity & VALID_GRANULARITIES) != 0 && Integer.bitCount(granularity) == 1; } } break; case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT: case AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT: { if (arguments.size() == 1) { String element = arguments.getString( AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING); return !TextUtils.isEmpty(element); } } break; } return false; } private void enforceCallingPermission(String permission, String function) { if (OWN_PROCESS_ID == Binder.getCallingPid()) { return; Loading Loading
api/current.txt +14 −3 Original line number Diff line number Diff line Loading @@ -24930,6 +24930,7 @@ package android.view.accessibility { method public static java.lang.String eventTypeToString(int); method public long getEventTime(); method public int getEventType(); method public int getGranularity(); method public java.lang.CharSequence getPackageName(); method public android.view.accessibility.AccessibilityRecord getRecord(int); method public int getRecordCount(); Loading @@ -24939,6 +24940,7 @@ package android.view.accessibility { method public static android.view.accessibility.AccessibilityEvent obtain(); method public void setEventTime(long); method public void setEventType(int); method public void setGranularity(int); method public void setPackageName(java.lang.CharSequence); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; Loading @@ -24960,6 +24962,7 @@ package android.view.accessibility { field public static final int TYPE_VIEW_SELECTED = 4; // 0x4 field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10 field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000 field public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY = 131072; // 0x20000 field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800 field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20 } Loading Loading @@ -25000,7 +25003,7 @@ package android.view.accessibility { method public int getChildCount(); method public java.lang.CharSequence getClassName(); method public java.lang.CharSequence getContentDescription(); method public java.lang.CharSequence[] getGranularities(); method public int getGranularities(); method public java.lang.CharSequence getPackageName(); method public android.view.accessibility.AccessibilityNodeInfo getParent(); method public java.lang.CharSequence getText(); Loading Loading @@ -25034,7 +25037,7 @@ package android.view.accessibility { method public void setEnabled(boolean); method public void setFocusable(boolean); method public void setFocused(boolean); method public void setGranularities(java.lang.CharSequence[]); method public void setGranularities(int); method public void setLongClickable(boolean); method public void setPackageName(java.lang.CharSequence); method public void setParent(android.view.View); Loading @@ -25047,7 +25050,8 @@ package android.view.accessibility { method public void setText(java.lang.CharSequence); 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_GRANULARITY = "ACTION_ARGUMENT_GRANULARITY"; field public static final java.lang.String ACTION_ARGUMENT_GRANULARITY_INT = "ACTION_ARGUMENT_GRANULARITY_INT"; field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING"; 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 Loading @@ -25055,11 +25059,18 @@ package android.view.accessibility { 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_GRANULARITY = 256; // 0x100 field public static final int ACTION_NEXT_HTML_ELEMENT = 1024; // 0x400 field public static final int ACTION_PREVIOUS_AT_GRANULARITY = 512; // 0x200 field public static final int ACTION_PREVIOUS_HTML_ELEMENT = 2048; // 0x800 field public static final int ACTION_SELECT = 4; // 0x4 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 field public static final int GRANULARITY_CHARACTER = 1; // 0x1 field public static final int GRANULARITY_LINE = 4; // 0x4 field public static final int GRANULARITY_PAGE = 16; // 0x10 field public static final int GRANULARITY_PARAGRAPH = 8; // 0x8 field public static final int GRANULARITY_WORD = 2; // 0x2 } public abstract class AccessibilityNodeProvider {
core/java/android/view/accessibility/AccessibilityEvent.java +52 −0 Original line number Diff line number Diff line Loading @@ -226,6 +226,23 @@ import java.util.List; * <li>{@link #getContentDescription()} - The content description of the source.</li> * </ul> * </p> * <b>View text traversed at granularity</b> - represents the event of traversing the * text of a view at a given granularity. For example, moving to the next word.</br> * <em>Type:</em> {@link #TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY} </br> * <em>Properties:</em></br> * <ul> * <li>{@link #getEventType()} - The type of the event.</li> * <li>{@link #getSource()} - The source info (for registered clients).</li> * <li>{@link #getClassName()} - The class name of the source.</li> * <li>{@link #getPackageName()} - The package name of the source.</li> * <li>{@link #getEventTime()} - The event time.</li> * <li>{@link #getText()} - The text of the current text at the granularity.</li> * <li>{@link #isPassword()} - Whether the source is password.</li> * <li>{@link #isEnabled()} - Whether the source is enabled.</li> * <li>{@link #getContentDescription()} - The content description of the source.</li> * <li>{@link #getGranularity()} - Sets the granularity at which a view's text was traversed.</li> * </ul> * </p> * <p> * <b>View scrolled</b> - represents the event of scrolling a view. If * the source is a descendant of {@link android.widget.AdapterView} the Loading Loading @@ -579,6 +596,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par */ public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000; /** * Represents the event of traversing the text of a view at a given granularity. */ public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY = 0x00020000; /** * Mask for {@link AccessibilityEvent} all types. * Loading @@ -597,6 +619,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * @see #TYPE_VIEW_SCROLLED * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED * @see #TYPE_ANNOUNCEMENT * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY */ public static final int TYPES_ALL_MASK = 0xFFFFFFFF; Loading @@ -610,6 +633,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par private int mEventType; private CharSequence mPackageName; private long mEventTime; int mGranularity; private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>(); Loading @@ -627,6 +651,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par void init(AccessibilityEvent event) { super.init(event); mEventType = event.mEventType; mGranularity = event.mGranularity; mEventTime = event.mEventTime; mPackageName = event.mPackageName; } Loading Loading @@ -743,6 +768,27 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par mPackageName = packageName; } /** * Sets the text granularity that was traversed. * * @param granularity The granularity. * * @throws IllegalStateException If called from an AccessibilityService. */ public void setGranularity(int granularity) { enforceNotSealed(); mGranularity = granularity; } /** * Gets the text granularity that was traversed. * * @return The granularity. */ public int getGranularity() { return mGranularity; } /** * Returns a cached instance if such is available or a new one is * instantiated with its type property set. Loading Loading @@ -831,6 +877,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par protected void clear() { super.clear(); mEventType = 0; mGranularity = 0; mPackageName = null; mEventTime = 0; while (!mRecords.isEmpty()) { Loading @@ -847,6 +894,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par public void initFromParcel(Parcel parcel) { mSealed = (parcel.readInt() == 1); mEventType = parcel.readInt(); mGranularity = parcel.readInt(); mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); mEventTime = parcel.readLong(); mConnectionId = parcel.readInt(); Loading Loading @@ -897,6 +945,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(isSealed() ? 1 : 0); parcel.writeInt(mEventType); parcel.writeInt(mGranularity); TextUtils.writeToParcel(mPackageName, parcel, 0); parcel.writeLong(mEventTime); parcel.writeInt(mConnectionId); Loading Loading @@ -953,6 +1002,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par builder.append("EventType: ").append(eventTypeToString(mEventType)); builder.append("; EventTime: ").append(mEventTime); builder.append("; PackageName: ").append(mPackageName); builder.append("; Granularity: ").append(mGranularity); builder.append(super.toString()); if (DEBUG) { builder.append("\n"); Loading Loading @@ -1033,6 +1083,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par return "TYPE_VIEW_ACCESSIBILITY_FOCUSED"; case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED"; case TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY: return "TYPE_CURRENT_AT_GRANULARITY_CHANGED"; default: return null; } Loading
core/java/android/view/accessibility/AccessibilityNodeInfo.java +142 −65 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ public class AccessibilityNodeInfo implements Parcelable { public static final int ACTION_CLEAR_SELECTION = 0x00000008; /** * Action that clicks on the node info. * Action that long clicks on the node info. */ public static final int ACTION_CLICK = 0x00000010; Loading @@ -122,78 +122,105 @@ public class AccessibilityNodeInfo implements Parcelable { public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080; /** * Action that requests from the node to go to the next entity in its content * at a given granularity. For example, move to the next word, link, etc. * <p> * <strong>Arguments:</strong> * <ul> * <li> * {@link #ACTION_ARGUMENT_GRANULARITY} * </li> * <li> * </p> * Action that requests to go to the next entity in this node's text * at a given granularity. For example, move to the next character, word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <code><pre><p> * // Assume the first granularity was presented to the user and she is * // making an explicit action to traverse the node at that granularity. * CharSequence granularity = info.getGranularity(0); * Bundle arguments = new Bundle(); * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY, granularity); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT, * AccessibilityNodeInfo.GRANULARITY_CHARACTER); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY, arguments); * </code></pre></p> * </li> * </ul> * </p> * @see #setGranularities(CharSequence[]) * * @see #setGranularities(int) * @see #getGranularities() * * @see #GRANULARITY_CHARACTER * @see #GRANULARITY_WORD * @see #GRANULARITY_LINE * @see #GRANULARITY_PARAGRAPH * @see #GRANULARITY_PAGE */ public static final int ACTION_NEXT_AT_GRANULARITY = 0x00000100; /** * Action that requests from the node to go to the previous entity in its content * at a given granularity. For example, move to the next word, link, etc. * <p> * <strong>Arguments:</strong> * <ul> * <li> * {@link #ACTION_ARGUMENT_GRANULARITY} * </li> * <li> * </p> * Action that requests to go to the previous entity in this node's text * at a given granularity. For example, move to the next character, word, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_GRANULARITY_INT}<br> * <strong>Example:</strong> * <code><pre><p> * // Assume the first granularity was presented to the user and she is * // making an explicit action to traverse the node at that granularity. * CharSequence granularity = info.getGranularity(0); * Bundle arguments = new Bundle(); * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY, granularity); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY, arguments); * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT, * AccessibilityNodeInfo.GRANULARITY_CHARACTER); * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY, arguments); * </code></pre></p> * </li> * </ul> * </p> * @see #setGranularities(CharSequence[]) * * @see #setGranularities(int) * @see #getGranularities() * * @see #GRANULARITY_CHARACTER * @see #GRANULARITY_WORD * @see #GRANULARITY_LINE * @see #GRANULARITY_PARAGRAPH * @see #GRANULARITY_PAGE */ public static final int ACTION_PREVIOUS_AT_GRANULARITY = 0x00000200; /** * Argument for which content granularity to be used when traversing the node content. * Action to move to the next HTML element of a given type. For example, move * to the BUTTON, INPUT, TABLE, etc. * <p> * <strong>Actions:</strong> * <ul> * <li> * {@link #ACTION_PREVIOUS_AT_GRANULARITY} * </li> * <li> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> * <strong>Example:</strong> * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments); * </code></pre></p> * </p> */ public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400; /** * Action to move to the previous HTML element of a given type. For example, move * to the BUTTON, INPUT, TABLE, etc. * <p> * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> * <strong>Example:</strong> * <code><pre><p> * Bundle arguments = new Bundle(); * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments); * </code></pre></p> * </p> */ public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800; /** * Argument for which text granularity to be used when traversing the node text. * <p> * <strong>Type:</strong> int<br> * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_GRANULARITY}, * {@link #ACTION_PREVIOUS_AT_GRANULARITY} * </li> * </ul> * </p> */ public static final String ACTION_ARGUMENT_GRANULARITY = "ACTION_ARGUMENT_GRANULARITY"; public static final String ACTION_ARGUMENT_GRANULARITY_INT = "ACTION_ARGUMENT_GRANULARITY_INT"; /** * Argument for which HTML element to get moving to the next/previous HTML element. * <p> * <strong>Type:</strong> String<br> * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT}, * {@link #ACTION_PREVIOUS_HTML_ELEMENT} * </p> */ public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING"; /** * The input focus. Loading @@ -205,6 +232,33 @@ public class AccessibilityNodeInfo implements Parcelable { */ public static final int FOCUS_ACCESSIBILITY = 2; // Granularities /** * Granularity bit for traversing the text of a node by character. */ public static final int GRANULARITY_CHARACTER = 0x00000001; /** * Granularity bit for traversing the text of a node by word. */ public static final int GRANULARITY_WORD = 0x00000002; /** * Granularity bit for traversing the text of a node by line. */ public static final int GRANULARITY_LINE = 0x00000004; /** * Granularity bit for traversing the text of a node by paragraph. */ public static final int GRANULARITY_PARAGRAPH = 0x00000008; /** * Granularity bit for traversing the text of a node by page. */ public static final int GRANULARITY_PAGE = 0x00000010; // Boolean attributes. private static final int PROPERTY_CHECKABLE = 0x00000001; Loading Loading @@ -308,7 +362,7 @@ public class AccessibilityNodeInfo implements Parcelable { private final SparseLongArray mChildNodeIds = new SparseLongArray(); private int mActions; private CharSequence[] mGranularities; private int mGranularities; private int mConnectionId = UNDEFINED; Loading Loading @@ -532,28 +586,28 @@ public class AccessibilityNodeInfo implements Parcelable { } /** * Sets the granularities for traversing the content of this node. * Sets the text granularities for traversing the text of this node. * <p> * <strong>Note:</strong> Cannot be called from an * {@link android.accessibilityservice.AccessibilityService}. * This class is made immutable before being delivered to an AccessibilityService. * </p> * * @param granularities The granularity names. * @param granularities The bit mask with granularities. * * @throws IllegalStateException If called from an AccessibilityService. */ public void setGranularities(CharSequence[] granularities) { public void setGranularities(int granularities) { enforceNotSealed(); mGranularities = granularities; } /** * Gets the granularities for traversing the content of this node. * Gets the granularities for traversing the text of this node. * * @return The count. * @return The bit mask with granularities. */ public CharSequence[] getGranularities() { public int getGranularities() { return mGranularities; } Loading Loading @@ -1339,8 +1393,6 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeLong(mParentNodeId); parcel.writeInt(mConnectionId); parcel.writeCharSequenceArray(mGranularities); SparseLongArray childIds = mChildNodeIds; final int childIdsSize = childIds.size(); parcel.writeInt(childIdsSize); Loading @@ -1360,6 +1412,8 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeInt(mActions); parcel.writeInt(mGranularities); parcel.writeInt(mBooleanProperties); parcel.writeCharSequence(mPackageName); Loading Loading @@ -1392,7 +1446,7 @@ public class AccessibilityNodeInfo implements Parcelable { mContentDescription = other.mContentDescription; mActions= other.mActions; mBooleanProperties = other.mBooleanProperties; mGranularities = (other.mGranularities) != null ? other.mGranularities.clone() : null; mGranularities = other.mGranularities; final int otherChildIdCount = other.mChildNodeIds.size(); for (int i = 0; i < otherChildIdCount; i++) { mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i)); Loading @@ -1411,8 +1465,6 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = parcel.readLong(); mConnectionId = parcel.readInt(); mGranularities = parcel.readCharSequenceArray(); SparseLongArray childIds = mChildNodeIds; final int childrenSize = parcel.readInt(); for (int i = 0; i < childrenSize; i++) { Loading @@ -1432,6 +1484,8 @@ public class AccessibilityNodeInfo implements Parcelable { mActions = parcel.readInt(); mGranularities = parcel.readInt(); mBooleanProperties = parcel.readInt(); mPackageName = parcel.readCharSequence(); Loading @@ -1449,7 +1503,7 @@ public class AccessibilityNodeInfo implements Parcelable { mParentNodeId = ROOT_NODE_ID; mWindowId = UNDEFINED; mConnectionId = UNDEFINED; mGranularities = null; mGranularities = 0; mChildNodeIds.clear(); mBoundsInParent.set(0, 0, 0, 0); mBoundsInScreen.set(0, 0, 0, 0); Loading Loading @@ -1482,6 +1536,29 @@ public class AccessibilityNodeInfo implements Parcelable { } } /** * Gets the human readable granularity symbolic name. * * @param granularity The action. * @return The symbolic name. */ private static String getGranularitySymbolicName(int granularity) { switch (granularity) { case GRANULARITY_CHARACTER: return "GRANULARITY_CHARACTER"; case GRANULARITY_WORD: return "GRANULARITY_WORD"; case GRANULARITY_LINE: return "GRANULARITY_LINE"; case GRANULARITY_PARAGRAPH: return "GRANULARITY_PARAGRAPH"; case GRANULARITY_PAGE: return "GRANULARITY_PAGE"; default: throw new IllegalArgumentException("Unknown granularity: " + granularity); } } private boolean canPerformRequestOverConnection(long accessibilityNodeId) { return (mWindowId != UNDEFINED && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED Loading Loading @@ -1529,11 +1606,13 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId)); builder.append("; mParentNodeId: " + mParentNodeId); CharSequence[] granularities = mGranularities; int granularities = mGranularities; builder.append("; granularities: ["); for (int i = 0, count = granularities.length; i < count; i++) { builder.append(granularities[i]); if (i < count - 1) { while (granularities != 0) { final int granularity = 1 << Integer.numberOfTrailingZeros(granularities); granularities &= ~granularity; builder.append(getGranularitySymbolicName(granularity)); if (granularities != 0) { builder.append(", "); } } Loading Loading @@ -1570,7 +1649,6 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; scrollable: " + isScrollable()); builder.append("; ["); for (int actionBits = mActions; actionBits != 0;) { final int action = 1 << Integer.numberOfTrailingZeros(actionBits); actionBits &= ~action; Loading @@ -1579,7 +1657,6 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append(", "); } } builder.append("]"); return builder.toString(); Loading
services/java/com/android/server/accessibility/AccessibilityManagerService.java +38 −4 Original line number Diff line number Diff line Loading @@ -1554,7 +1554,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub IAccessibilityInteractionConnection connection = null; synchronized (mLock) { final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this, resolvedWindowId, action); resolvedWindowId, action, arguments); if (!permissionGranted) { return false; } else { Loading Loading @@ -1702,7 +1702,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub | AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS | AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY; | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT; private static final int VALID_GRANULARITIES = AccessibilityNodeInfo.GRANULARITY_CHARACTER | AccessibilityNodeInfo.GRANULARITY_WORD | AccessibilityNodeInfo.GRANULARITY_LINE | AccessibilityNodeInfo.GRANULARITY_PARAGRAPH | AccessibilityNodeInfo.GRANULARITY_PAGE; private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = AccessibilityEvent.TYPE_VIEW_CLICKED Loading Loading @@ -1752,10 +1761,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId); } public boolean canPerformActionLocked(Service service, int windowId, int action) { public boolean canPerformActionLocked(Service service, int windowId, int action, Bundle arguments) { return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId) && isActionPermitted(action); && isActionPermitted(action) && isActionArgumentsValid(action, arguments); } public boolean canRetrieveWindowContent(Service service) { Loading @@ -1779,6 +1790,29 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return (VALID_ACTIONS & action) != 0; } private boolean isActionArgumentsValid(int action, Bundle arguments) { switch (action) { case AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY: case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY: { if (arguments.size() == 1) { final int granularity = arguments.getInt( AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT); return (granularity & VALID_GRANULARITIES) != 0 && Integer.bitCount(granularity) == 1; } } break; case AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT: case AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT: { if (arguments.size() == 1) { String element = arguments.getString( AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING); return !TextUtils.isEmpty(element); } } break; } return false; } private void enforceCallingPermission(String permission, String function) { if (OWN_PROCESS_ID == Binder.getCallingPid()) { return; Loading