Remove activation gestures form reported and add a touch explore requesting flag.

1. Delegating activation gestures has several issues that we should
   decide how to handle if possible before allowing an accessibility
   service to take over them:

   A) It is needed that every view than can be clicked or long pressed on
      reacts to such as a response to calling performClick and performLongPress
      which is not necessary true since the view may watch the touch
      events and do its own click long click detection. As a result it may
      be possible that there are view a user cannot interact with in
      touch exploration mode but can if not in that mode.

   B) Clicking or long pressing on a different location in a view may yield
      different results, for example NumberPicker. Ideally such views have
      to implement AccessibilityNodeProvide which provider handles correctly
      the request for click long press on virtual nodes. Some apps however
      just fire different hover accessibility events when the user is over
      a specific semantic portion of the view but do not provide virtual
      nodes. Hence, a user will not be able to interact with such semantic
      regions but the system can achieve that by sending the click/long click
      at the precise location in the view that was last touch explored.

2. Adding a flag on accessibility service info to request explore by touch
   mode. There is no need to put the device in this mode if node of the currently
   enabled accessibility services supports it. Now the problem is inverted and
   the service has to explicitly state its capability.

3. Fixing a bug where includeImportantViews was ignored for automation
   services.

Change-Id: I3b29a19f24ab5e26ee29f974bbac2197614c9e2a
This commit is contained in:
Svetoslav Ganov
2012-05-09 11:02:38 -07:00
parent e2d47e63cf
commit e4abc512aa
7 changed files with 40 additions and 64 deletions

View File

@@ -315,7 +315,6 @@ package android {
field public static final int cacheColorHint = 16843009; // 0x1010101 field public static final int cacheColorHint = 16843009; // 0x1010101
field public static final int calendarViewShown = 16843596; // 0x101034c field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canHandleGestures = 16843691; // 0x10103ab
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385 field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230 field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
field public static final deprecated int capitalize = 16843113; // 0x1010169 field public static final deprecated int capitalize = 16843113; // 0x1010169
@@ -754,7 +753,7 @@ package android {
field public static final int pathPrefix = 16842795; // 0x101002b field public static final int pathPrefix = 16842795; // 0x101002b
field public static final int permission = 16842758; // 0x1010006 field public static final int permission = 16842758; // 0x1010006
field public static final int permissionGroup = 16842762; // 0x101000a field public static final int permissionGroup = 16842762; // 0x101000a
field public static final int permissionGroupFlags = 16843692; // 0x10103ac field public static final int permissionGroupFlags = 16843691; // 0x10103ab
field public static final int persistent = 16842765; // 0x101000d field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee field public static final int persistentDrawingCache = 16842990; // 0x10100ee
field public static final deprecated int phoneNumber = 16843111; // 0x1010167 field public static final deprecated int phoneNumber = 16843111; // 0x1010167
@@ -2017,7 +2016,6 @@ package android.accessibilityservice {
method protected void onServiceConnected(); method protected void onServiceConnected();
method public final boolean performGlobalAction(int); method public final boolean performGlobalAction(int);
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo); method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
field public static final int GESTURE_DOUBLE_TAP = 17; // 0x11
field public static final int GESTURE_SWIPE_DOWN = 2; // 0x2 field public static final int GESTURE_SWIPE_DOWN = 2; // 0x2
field public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15; // 0xf field public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15; // 0xf
field public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16; // 0x10 field public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16; // 0x10
@@ -2034,7 +2032,6 @@ package android.accessibilityservice {
field public static final int GESTURE_SWIPE_UP_AND_DOWN = 7; // 0x7 field public static final int GESTURE_SWIPE_UP_AND_DOWN = 7; // 0x7
field public static final int GESTURE_SWIPE_UP_AND_LEFT = 13; // 0xd field public static final int GESTURE_SWIPE_UP_AND_LEFT = 13; // 0xd
field public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14; // 0xe field public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14; // 0xe
field public static final int GESTURE_TAP_AND_HOLD = 18; // 0x12
field public static final int GLOBAL_ACTION_BACK = 1; // 0x1 field public static final int GLOBAL_ACTION_BACK = 1; // 0x1
field public static final int GLOBAL_ACTION_HOME = 2; // 0x2 field public static final int GLOBAL_ACTION_HOME = 2; // 0x2
field public static final int GLOBAL_ACTION_NOTIFICATIONS = 4; // 0x4 field public static final int GLOBAL_ACTION_NOTIFICATIONS = 4; // 0x4
@@ -2048,7 +2045,6 @@ package android.accessibilityservice {
method public int describeContents(); method public int describeContents();
method public static java.lang.String feedbackTypeToString(int); method public static java.lang.String feedbackTypeToString(int);
method public static java.lang.String flagToString(int); method public static java.lang.String flagToString(int);
method public boolean getCanHandleGestures();
method public boolean getCanRetrieveWindowContent(); method public boolean getCanRetrieveWindowContent();
method public deprecated java.lang.String getDescription(); method public deprecated java.lang.String getDescription();
method public java.lang.String getId(); method public java.lang.String getId();
@@ -2064,7 +2060,8 @@ package android.accessibilityservice {
field public static final int FEEDBACK_HAPTIC = 2; // 0x2 field public static final int FEEDBACK_HAPTIC = 2; // 0x2
field public static final int FEEDBACK_SPOKEN = 1; // 0x1 field public static final int FEEDBACK_SPOKEN = 1; // 0x1
field public static final int FEEDBACK_VISUAL = 8; // 0x8 field public static final int FEEDBACK_VISUAL = 8; // 0x8
field public static final int INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2 field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
field public int eventTypes; field public int eventTypes;
field public int feedbackType; field public int feedbackType;
field public int flags; field public int flags;

View File

@@ -283,16 +283,6 @@ public abstract class AccessibilityService extends Service {
*/ */
public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16; public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16;
/**
* The user has performed a double tap gesture on the touch screen.
*/
public static final int GESTURE_DOUBLE_TAP = 17;
/**
* The user has performed a tap and hold gesture on the touch screen.
*/
public static final int GESTURE_TAP_AND_HOLD = 18;
/** /**
* The {@link Intent} that must be declared as handled by the service. * The {@link Intent} that must be declared as handled by the service.
*/ */
@@ -377,14 +367,12 @@ public abstract class AccessibilityService extends Service {
/** /**
* Called by the system when the user performs a specific gesture on the * Called by the system when the user performs a specific gesture on the
* touch screen. If the gesture is not handled in this callback the system * touch screen.
* may provide default handing. Therefore, one should return true from this
* function if overriding of default behavior is desired.
* *
* <strong>Note:</strong> To receive gestures an accessibility service * <strong>Note:</strong> To receive gestures an accessibility service must
* must declare that it can handle such by specifying the * request that the device is in touch exploration mode by setting the
* <code>&lt;{@link android.R.styleable#AccessibilityService_canHandleGestures * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}
* canHandleGestures}&gt;</code> attribute. * flag.
* *
* @param gestureId The unique id of the performed gesture. * @param gestureId The unique id of the performed gesture.
* *
@@ -406,13 +394,8 @@ public abstract class AccessibilityService extends Service {
* @see #GESTURE_SWIPE_RIGHT_AND_UP * @see #GESTURE_SWIPE_RIGHT_AND_UP
* @see #GESTURE_SWIPE_RIGHT_AND_LEFT * @see #GESTURE_SWIPE_RIGHT_AND_LEFT
* @see #GESTURE_SWIPE_RIGHT_AND_DOWN * @see #GESTURE_SWIPE_RIGHT_AND_DOWN
* @see #GESTURE_CLOCKWISE_CIRCLE
* @see #GESTURE_COUNTER_CLOCKWISE_CIRCLE
* @see #GESTURE_DOUBLE_TAP
* @see #GESTURE_TAP_AND_HOLD
*/ */
protected boolean onGesture(int gestureId) { protected boolean onGesture(int gestureId) {
// TODO: Describe the default gesture processing in the javaDoc once it is finalized.
return false; return false;
} }

View File

@@ -131,7 +131,19 @@ public class AccessibilityServiceInfo implements Parcelable {
* elements. * elements.
* </p> * </p>
*/ */
public static final int INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002; public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002;
/**
* This flag requests that the system gets into touch exploration mode.
* In this mode a single finger moving on the screen behaves as a mouse
* pointer hovering over the user interface. The system will also detect
* certain gestures performed on the touch screen and notify this service.
* The system will enable touch exploration mode if there is at least one
* accessibility service that has this flag set. Hence, clearing this
* flag does not guarantee that the device will not be in touch exploration
* mode since there may be another enabled service that requested it.
*/
public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE= 0x0000004;
/** /**
* The event types an {@link AccessibilityService} is interested in. * The event types an {@link AccessibilityService} is interested in.
@@ -198,7 +210,8 @@ public class AccessibilityServiceInfo implements Parcelable {
* <strong>Can be dynamically set at runtime.</strong> * <strong>Can be dynamically set at runtime.</strong>
* </p> * </p>
* @see #DEFAULT * @see #DEFAULT
* @see #INCLUDE_NOT_IMPORTANT_VIEWS * @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
* @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
*/ */
public int flags; public int flags;
@@ -223,11 +236,6 @@ public class AccessibilityServiceInfo implements Parcelable {
*/ */
private boolean mCanRetrieveWindowContent; private boolean mCanRetrieveWindowContent;
/**
* Flag whether this accessibility service can handle gestures.
*/
private boolean mCanHandleGestures;
/** /**
* Resource id of the description of the accessibility service. * Resource id of the description of the accessibility service.
*/ */
@@ -308,8 +316,6 @@ public class AccessibilityServiceInfo implements Parcelable {
mCanRetrieveWindowContent = asAttributes.getBoolean( mCanRetrieveWindowContent = asAttributes.getBoolean(
com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent, com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent,
false); false);
mCanHandleGestures = asAttributes.getBoolean(
com.android.internal.R.styleable.AccessibilityService_canHandleGestures, false);
TypedValue peekedValue = asAttributes.peekValue( TypedValue peekedValue = asAttributes.peekValue(
com.android.internal.R.styleable.AccessibilityService_description); com.android.internal.R.styleable.AccessibilityService_description);
if (peekedValue != null) { if (peekedValue != null) {
@@ -391,18 +397,6 @@ public class AccessibilityServiceInfo implements Parcelable {
return mCanRetrieveWindowContent; return mCanRetrieveWindowContent;
} }
/**
* Whether this service can handle gestures.
* <p>
* <strong>Statically set from
* {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
* </p>
* @return True if the service can handle gestures.
*/
public boolean getCanHandleGestures() {
return mCanHandleGestures;
}
/** /**
* Gets the non-localized description of the accessibility service. * Gets the non-localized description of the accessibility service.
* <p> * <p>
@@ -614,8 +608,10 @@ public class AccessibilityServiceInfo implements Parcelable {
switch (flag) { switch (flag) {
case DEFAULT: case DEFAULT:
return "DEFAULT"; return "DEFAULT";
case INCLUDE_NOT_IMPORTANT_VIEWS: case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS:
return "REGARD_VIEWS_NOT_IMPORTANT_FOR_ACCESSIBILITY"; return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS";
case FLAG_REQUEST_TOUCH_EXPLORATION_MODE:
return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE";
default: default:
return null; return null;
} }

View File

@@ -189,7 +189,7 @@ public class UiTestAutomationBridge {
final AccessibilityServiceInfo info = new AccessibilityServiceInfo(); final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
info.flags |= AccessibilityServiceInfo.INCLUDE_NOT_IMPORTANT_VIEWS; info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
try { try {
manager.registerUiTestAutomationService(mListener, info); manager.registerUiTestAutomationService(mListener, info);

View File

@@ -2461,8 +2461,10 @@
<attr name="accessibilityFlags"> <attr name="accessibilityFlags">
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} --> <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} -->
<flag name="flagDefault" value="0x00000001" /> <flag name="flagDefault" value="0x00000001" />
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#INCLUDE_NOT_IMPORTANT_VIEWS} --> <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} -->
<flag name="flagIncludeNotImportantViews" value="0x00000002" /> <flag name="flagIncludeNotImportantViews" value="0x00000002" />
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} -->
<flag name="flagRequestTouchExplorationMode" value="0x00000004" />
</attr> </attr>
<!-- Component name of an activity that allows the user to modify <!-- Component name of an activity that allows the user to modify
the settings for this service. This setting cannot be changed at runtime. --> the settings for this service. This setting cannot be changed at runtime. -->
@@ -2470,8 +2472,6 @@
<!-- Flag whether the accessibility service wants to be able to retrieve the <!-- Flag whether the accessibility service wants to be able to retrieve the
active window content. This setting cannot be changed at runtime. --> active window content. This setting cannot be changed at runtime. -->
<attr name="canRetrieveWindowContent" format="boolean" /> <attr name="canRetrieveWindowContent" format="boolean" />
<!-- Flag whether the accessibility service can handle gesrures and wants such. -->
<attr name="canHandleGestures" format="boolean" />
<!-- Short description of the accessibility serivce purpose or behavior.--> <!-- Short description of the accessibility serivce purpose or behavior.-->
<attr name="description" /> <attr name="description" />
</declare-styleable> </declare-styleable>

View File

@@ -3600,7 +3600,6 @@
<public type="attr" name="parentActivityName" /> <public type="attr" name="parentActivityName" />
<public type="attr" name="importantForAccessibility"/> <public type="attr" name="importantForAccessibility"/>
<public type="attr" name="canHandleGestures"/>
<public type="attr" name="permissionGroupFlags"/> <public type="attr" name="permissionGroupFlags"/>

View File

@@ -17,7 +17,7 @@
package com.android.server.accessibility; package com.android.server.accessibility;
import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
import static android.accessibilityservice.AccessibilityServiceInfo.INCLUDE_NOT_IMPORTANT_VIEWS; import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
import android.Manifest; import android.Manifest;
import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityService;
@@ -531,12 +531,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
// last record in the enabled services setting. Ideally, // last record in the enabled services setting. Ideally,
// the user should make the call which service handles // the user should make the call which service handles
// gestures. However, only one service should handle // gestures. However, only one service should handle
// gestrues to avoid user frustration when different // gestures to avoid user frustration when different
// bahiour is observed from different combinations of // behavior is observed from different combinations of
// enabled accessibility services. // enabled accessibility services.
for (int i = mServices.size() - 1; i >= 0; i--) { for (int i = mServices.size() - 1; i >= 0; i--) {
Service service = mServices.get(i); Service service = mServices.get(i);
if (service.mCanHandleGestures && service.mIsDefault == isDefault) { if (service.mReqeustTouchExplorationMode && service.mIsDefault == isDefault) {
mGestureHandler.scheduleHandleGesture(gestureId, service.mServiceInterface); mGestureHandler.scheduleHandleGesture(gestureId, service.mServiceInterface);
return true; return true;
} }
@@ -1225,7 +1225,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
boolean mCanRetrieveScreenContent; boolean mCanRetrieveScreenContent;
boolean mCanHandleGestures; boolean mReqeustTouchExplorationMode;
boolean mIsAutomation; boolean mIsAutomation;
@@ -1243,7 +1243,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mIsAutomation = isAutomation; mIsAutomation = isAutomation;
if (!isAutomation) { if (!isAutomation) {
mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent(); mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent();
mCanHandleGestures = accessibilityServiceInfo.getCanHandleGestures(); mReqeustTouchExplorationMode =
(accessibilityServiceInfo.flags
& AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
mIntent = new Intent().setComponent(mComponentName); mIntent = new Intent().setComponent(mComponentName);
mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.accessibility_binding_label); com.android.internal.R.string.accessibility_binding_label);
@@ -1251,7 +1253,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
} else { } else {
mCanRetrieveScreenContent = true; mCanRetrieveScreenContent = true;
mCanHandleGestures = true;
} }
setDynamicallyConfigurableProperties(accessibilityServiceInfo); setDynamicallyConfigurableProperties(accessibilityServiceInfo);
} }
@@ -1272,7 +1273,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
// >= Build.VERSION_CODES.JELLY_BEAN) { // >= Build.VERSION_CODES.JELLY_BEAN) {
> Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
mIncludeNotImportantViews = mIncludeNotImportantViews =
(info.flags & INCLUDE_NOT_IMPORTANT_VIEWS) != 0; (info.flags & FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0;
} }
synchronized (mLock) { synchronized (mLock) {