Skip to content

Commit 4213804

Browse files
committed
Accessibility focus - framework
Usefulness: Keep track of the current user location in the screen when traversing the it. Enabling structural and directional navigation over all elements on the screen. This enables blind users that know the application layout to efficiently locate desired elements as opposed to try touch exploring the region where the the element should be - very tedious. Rationale: There are two ways to implement accessibility focus One is to let accessibility services keep track of it since they have access to the screen content, and another to let the view hierarchy keep track of it. While the first approach would require almost no work on our part it poses several challenges which make it a sub-optimal choice. Having the accessibility focus in the accessibility service would require that service to scrape the window content every time it changes to sync the view tree state and the accessibility focus location. Pretty much the service will have to keep an off screen model of the screen content. This could be quite challenging to get right and would incur performance cost for the multiple IPCs to repeatedly fetch the screen content. Further, keeping virtual accessibility focus (i.e. in the service) would require sync of the input and accessibility focus. This could be challenging to implement right as well. Also, having an unlimited number of accessibility services we cannot guarantee that they will have a proper implementation, if any, to allow users to perform structural navigation of the screen content. Assuming two accessibility services implement structural navigation via accessibility focus, there is not guarantee that they will behave similarly by default, i.e. provide some standard way to navigate the screen content. Also feedback from experienced accessibility researchers, specifically T.V Raman, provides evidence that having virtual accessibility focus creates many issues and it is very hard to get right. Therefore, keeping accessibility focus in the system will avoid keeping an off-screen model in accessibility services, it will always be in sync with the state of the view hierarchy and the input focus. Also this will allow having a default behavior for traversing the screen via this accessibility focus that is consistent in all accessibility services. We provide accessibility services with APIs to override this behavior but all of them will perform screen traversal in a consistent way by default. Behavior: If accessibility is enabled the accessibility focus is the leading one and the input follows it. Putting accessibility focus on a view moves the input focus there. Clearing the accessibility focus of a view, clears the input focus of this view. If accessibility focus is on a view that cannot take input focus, then no other view should have input focus. In accessibility mode we initially give accessibility focus to the topmost view and no view has input focus. This ensures consistent behavior accross all apps. Note that accessibility focus can move hierarchically in the view tree and having it at the root is better than putting it where the input focus would be - at the first input focusable which could be at an arbitrary depth in the view tree. By default not all views are reported for accessibility, only the important ones. A view may be explicitly labeled as important or not for accessibility, or the system determines which one is such - default. Important views for accessibility are all views that are not dumb layout managers used only to arrange their chidren. Since the same content arrangement can be obtained via different combintation of layout managers, such managers cannot be used to reliably determine the application structure. For example, a user should see a list as a list view with several list items and each list item as a text view and a button as opposed to seeing all the layout managers used to arrange the list item's content. By default only important for accessibility views are regared for accessibility purposes. View not regarded for accessibility neither fire accessibility events, nor are reported being on the screen. An accessibility service may request the system to regard all views. If the target SDK of an accessibility services is less than JellyBean, then all views are regarded for accessibility. Note that an accessibility service that requires all view to be ragarded for accessibility may put accessibility focus on any view. Hence, it may implement any navigational paradigm if desired. Especially considering the fact that the system is detecting some standard gestures and delegates their processing to an accessibility service. The default implementation of an accessibility services performs the defualt navigation. bug:5932640 bug:5605641 Change-Id: Ieac461d480579d706a847b9325720cb254736ebe
1 parent dbed083 commit 4213804

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3952
-1265
lines changed

Android.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ LOCAL_SRC_FILES := $(filter-out \
6060
## READ ME: ########################################################
6161
LOCAL_SRC_FILES += \
6262
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
63-
core/java/android/accessibilityservice/IEventListener.aidl \
63+
core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
6464
core/java/android/accounts/IAccountManager.aidl \
6565
core/java/android/accounts/IAccountManagerResponse.aidl \
6666
core/java/android/accounts/IAccountAuthenticator.aidl \

api/current.txt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ package android {
534534
field public static final int imeSubtypeLocale = 16843500; // 0x10102ec
535535
field public static final int imeSubtypeMode = 16843501; // 0x10102ed
536536
field public static final int immersive = 16843456; // 0x10102c0
537+
field public static final int importantForAccessibility = 16843699; // 0x10103b3
537538
field public static final int inAnimation = 16843127; // 0x1010177
538539
field public static final int includeFontPadding = 16843103; // 0x101015f
539540
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -1993,11 +1994,23 @@ package android.accessibilityservice {
19931994

19941995
public abstract class AccessibilityService extends android.app.Service {
19951996
ctor public AccessibilityService();
1997+
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
19961998
method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
19971999
method public final android.os.IBinder onBind(android.content.Intent);
2000+
method protected void onGesture(int);
19982001
method public abstract void onInterrupt();
19992002
method protected void onServiceConnected();
20002003
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
2004+
field public static final int GESTURE_CLOCKWISE_CIRCLE = 9; // 0x9
2005+
field public static final int GESTURE_COUNTER_CLOCKWISE_CIRCLE = 10; // 0xa
2006+
field public static final int GESTURE_SWIPE_DOWN = 2; // 0x2
2007+
field public static final int GESTURE_SWIPE_DOWN_AND_UP = 8; // 0x8
2008+
field public static final int GESTURE_SWIPE_LEFT = 3; // 0x3
2009+
field public static final int GESTURE_SWIPE_LEFT_AND_RIGHT = 5; // 0x5
2010+
field public static final int GESTURE_SWIPE_RIGHT = 4; // 0x4
2011+
field public static final int GESTURE_SWIPE_RIGHT_AND_LEFT = 6; // 0x6
2012+
field public static final int GESTURE_SWIPE_UP = 1; // 0x1
2013+
field public static final int GESTURE_SWIPE_UP_AND_DOWN = 7; // 0x7
20012014
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
20022015
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
20032016
}
@@ -2022,6 +2035,7 @@ package android.accessibilityservice {
20222035
field public static final int FEEDBACK_HAPTIC = 2; // 0x2
20232036
field public static final int FEEDBACK_SPOKEN = 1; // 0x1
20242037
field public static final int FEEDBACK_VISUAL = 8; // 0x8
2038+
field public static final int INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
20252039
field public int eventTypes;
20262040
field public int feedbackType;
20272041
field public int flags;
@@ -23327,6 +23341,7 @@ package android.view {
2332723341
ctor public View(android.content.Context);
2332823342
ctor public View(android.content.Context, android.util.AttributeSet);
2332923343
ctor public View(android.content.Context, android.util.AttributeSet, int);
23344+
method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
2333023345
method public void addFocusables(java.util.ArrayList<android.view.View>, int);
2333123346
method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
2333223347
method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
@@ -23429,6 +23444,7 @@ package android.view {
2342923444
method public int getHorizontalFadingEdgeLength();
2343023445
method protected int getHorizontalScrollbarHeight();
2343123446
method public int getId();
23447+
method public int getImportantForAccessibility();
2343223448
method public boolean getKeepScreenOn();
2343323449
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
2343423450
method public int getLayerType();
@@ -23462,6 +23478,7 @@ package android.view {
2346223478
method public int getPaddingStart();
2346323479
method public int getPaddingTop();
2346423480
method public final android.view.ViewParent getParent();
23481+
method public android.view.ViewParent getParentForAccessibility();
2346523482
method public float getPivotX();
2346623483
method public float getPivotY();
2346723484
method public int getResolvedLayoutDirection();
@@ -23617,6 +23634,7 @@ package android.view {
2361723634
method public void onWindowSystemUiVisibilityChanged(int);
2361823635
method protected void onWindowVisibilityChanged(int);
2361923636
method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
23637+
method public boolean performAccessibilityAction(int);
2362023638
method public boolean performClick();
2362123639
method public boolean performHapticFeedback(int);
2362223640
method public boolean performHapticFeedback(int, int);
@@ -23688,6 +23706,7 @@ package android.view {
2368823706
method public void setHorizontalScrollBarEnabled(boolean);
2368923707
method public void setHovered(boolean);
2369023708
method public void setId(int);
23709+
method public void setImportantForAccessibility(int);
2369123710
method public void setKeepScreenOn(boolean);
2369223711
method public void setLayerType(int, android.graphics.Paint);
2369323712
method public void setLayoutDirection(int);
@@ -23762,6 +23781,14 @@ package android.view {
2376223781
method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
2376323782
method public boolean willNotCacheDrawing();
2376423783
method public boolean willNotDraw();
23784+
field public static final int ACCESSIBILITY_FOCUS_BACKWARD = 4097; // 0x1001
23785+
field public static final int ACCESSIBILITY_FOCUS_DOWN = 4226; // 0x1082
23786+
field public static final int ACCESSIBILITY_FOCUS_FORWARD = 4098; // 0x1002
23787+
field public static final int ACCESSIBILITY_FOCUS_IN = 4100; // 0x1004
23788+
field public static final int ACCESSIBILITY_FOCUS_LEFT = 4113; // 0x1011
23789+
field public static final int ACCESSIBILITY_FOCUS_OUT = 4104; // 0x1008
23790+
field public static final int ACCESSIBILITY_FOCUS_RIGHT = 4162; // 0x1042
23791+
field public static final int ACCESSIBILITY_FOCUS_UP = 4129; // 0x1021
2376523792
field public static final android.util.Property ALPHA;
2376623793
field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
2376723794
field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
@@ -23783,6 +23810,7 @@ package android.view {
2378323810
field protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
2378423811
field protected static final int[] FOCUSED_STATE_SET;
2378523812
field protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
23813+
field public static final int FOCUS_ACCESSIBILITY = 4096; // 0x1000
2378623814
field public static final int FOCUS_BACKWARD = 1; // 0x1
2378723815
field public static final int FOCUS_DOWN = 130; // 0x82
2378823816
field public static final int FOCUS_FORWARD = 2; // 0x2
@@ -23791,6 +23819,9 @@ package android.view {
2379123819
field public static final int FOCUS_UP = 33; // 0x21
2379223820
field public static final int GONE = 8; // 0x8
2379323821
field public static final int HAPTIC_FEEDBACK_ENABLED = 268435456; // 0x10000000
23822+
field public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0; // 0x0
23823+
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
23824+
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
2379423825
field public static final int INVISIBLE = 4; // 0x4
2379523826
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
2379623827
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -24215,6 +24246,7 @@ package android.view {
2421524246
method public abstract void focusableViewAvailable(android.view.View);
2421624247
method public abstract boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
2421724248
method public abstract android.view.ViewParent getParent();
24249+
method public abstract android.view.ViewParent getParentForAccessibility();
2421824250
method public abstract void invalidateChild(android.view.View, android.graphics.Rect);
2421924251
method public abstract android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
2422024252
method public abstract boolean isLayoutRequested();
@@ -24616,6 +24648,8 @@ package android.view.accessibility {
2461624648
field public static final int TYPE_NOTIFICATION_STATE_CHANGED = 64; // 0x40
2461724649
field public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 1024; // 0x400
2461824650
field public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 512; // 0x200
24651+
field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 32768; // 0x8000
24652+
field public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 65536; // 0x10000
2461924653
field public static final int TYPE_VIEW_CLICKED = 1; // 0x1
2462024654
field public static final int TYPE_VIEW_FOCUSED = 8; // 0x8
2462124655
field public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
@@ -24656,6 +24690,8 @@ package android.view.accessibility {
2465624690
method public void addChild(android.view.View, int);
2465724691
method public int describeContents();
2465824692
method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String);
24693+
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
24694+
method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int);
2465924695
method public int getActions();
2466024696
method public void getBoundsInParent(android.graphics.Rect);
2466124697
method public void getBoundsInScreen(android.graphics.Rect);
@@ -24667,6 +24703,7 @@ package android.view.accessibility {
2466724703
method public android.view.accessibility.AccessibilityNodeInfo getParent();
2466824704
method public java.lang.CharSequence getText();
2466924705
method public int getWindowId();
24706+
method public boolean isAccessibilityFocused();
2467024707
method public boolean isCheckable();
2467124708
method public boolean isChecked();
2467224709
method public boolean isClickable();
@@ -24683,6 +24720,7 @@ package android.view.accessibility {
2468324720
method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.accessibility.AccessibilityNodeInfo);
2468424721
method public boolean performAction(int);
2468524722
method public void recycle();
24723+
method public void setAccessibilityFocused(boolean);
2468624724
method public void setBoundsInParent(android.graphics.Rect);
2468724725
method public void setBoundsInScreen(android.graphics.Rect);
2468824726
method public void setCheckable(boolean);
@@ -24704,16 +24742,23 @@ package android.view.accessibility {
2470424742
method public void setSource(android.view.View, int);
2470524743
method public void setText(java.lang.CharSequence);
2470624744
method public void writeToParcel(android.os.Parcel, int);
24745+
field public static final int ACTION_ACCESSIBILITY_FOCUS = 16; // 0x10
24746+
field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 32; // 0x20
2470724747
field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
2470824748
field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
24749+
field public static final int ACTION_CLICK = 64; // 0x40
2470924750
field public static final int ACTION_FOCUS = 1; // 0x1
2471024751
field public static final int ACTION_SELECT = 4; // 0x4
2471124752
field public static final android.os.Parcelable.Creator CREATOR;
24753+
field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
24754+
field public static final int FOCUS_INPUT = 1; // 0x1
2471224755
}
2471324756

2471424757
public abstract class AccessibilityNodeProvider {
2471524758
ctor public AccessibilityNodeProvider();
24759+
method public android.view.accessibility.AccessibilityNodeInfo accessibilityFocusSearch(int, int);
2471624760
method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
24761+
method public android.view.accessibility.AccessibilityNodeInfo findAccessibilitiyFocus(int);
2471724762
method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int);
2471824763
method public boolean performAccessibilityAction(int, int);
2471924764
}

0 commit comments

Comments
 (0)