Skip to content

Commit f01d3dd

Browse files
sganovAndroid (Google) Code Review
authored andcommitted
Merge "Adding some more gestures and actions for accessibility."
2 parents f35ea5d + 005b83b commit f01d3dd

File tree

10 files changed

+235
-45
lines changed

10 files changed

+235
-45
lines changed

api/current.txt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,17 +1999,30 @@ package android.accessibilityservice {
19991999
method protected void onGesture(int);
20002000
method public abstract void onInterrupt();
20012001
method protected void onServiceConnected();
2002+
method public final boolean performGlobalAction(int);
20022003
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
20032004
field public static final int GESTURE_CLOCKWISE_CIRCLE = 9; // 0x9
20042005
field public static final int GESTURE_COUNTER_CLOCKWISE_CIRCLE = 10; // 0xa
20052006
field public static final int GESTURE_SWIPE_DOWN = 2; // 0x2
2007+
field public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 17; // 0x11
2008+
field public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 18; // 0x12
20062009
field public static final int GESTURE_SWIPE_DOWN_AND_UP = 8; // 0x8
20072010
field public static final int GESTURE_SWIPE_LEFT = 3; // 0x3
2011+
field public static final int GESTURE_SWIPE_LEFT_AND_DOWN = 12; // 0xc
20082012
field public static final int GESTURE_SWIPE_LEFT_AND_RIGHT = 5; // 0x5
2013+
field public static final int GESTURE_SWIPE_LEFT_AND_UP = 11; // 0xb
20092014
field public static final int GESTURE_SWIPE_RIGHT = 4; // 0x4
2015+
field public static final int GESTURE_SWIPE_RIGHT_AND_DOWN = 14; // 0xe
20102016
field public static final int GESTURE_SWIPE_RIGHT_AND_LEFT = 6; // 0x6
2017+
field public static final int GESTURE_SWIPE_RIGHT_AND_UP = 13; // 0xd
20112018
field public static final int GESTURE_SWIPE_UP = 1; // 0x1
20122019
field public static final int GESTURE_SWIPE_UP_AND_DOWN = 7; // 0x7
2020+
field public static final int GESTURE_SWIPE_UP_AND_LEFT = 15; // 0xf
2021+
field public static final int GESTURE_SWIPE_UP_AND_RIGHT = 16; // 0x10
2022+
field public static final int GLOBAL_ACTION_BACK = 1; // 0x1
2023+
field public static final int GLOBAL_ACTION_HOME = 2; // 0x2
2024+
field public static final int GLOBAL_ACTION_NOTIFICATIONS = 4; // 0x4
2025+
field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
20132026
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
20142027
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
20152028
}
@@ -25006,12 +25019,13 @@ package android.view.accessibility {
2500625019
method public void setSource(android.view.View, int);
2500725020
method public void setText(java.lang.CharSequence);
2500825021
method public void writeToParcel(android.os.Parcel, int);
25009-
field public static final int ACTION_ACCESSIBILITY_FOCUS = 16; // 0x10
25010-
field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 32; // 0x20
25022+
field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
25023+
field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
2501125024
field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
2501225025
field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
25013-
field public static final int ACTION_CLICK = 64; // 0x40
25026+
field public static final int ACTION_CLICK = 16; // 0x10
2501425027
field public static final int ACTION_FOCUS = 1; // 0x1
25028+
field public static final int ACTION_LONG_CLICK = 32; // 0x20
2501525029
field public static final int ACTION_SELECT = 4; // 0x4
2501625030
field public static final android.os.Parcelable.Creator CREATOR;
2501725031
field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2

core/java/android/accessibilityservice/AccessibilityService.java

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,52 @@ public abstract class AccessibilityService extends Service {
258258
*/
259259
public static final int GESTURE_COUNTER_CLOCKWISE_CIRCLE = 10;
260260

261+
/**
262+
* The user has performed a left and up gesture on the touch screen.
263+
*/
264+
public static final int GESTURE_SWIPE_LEFT_AND_UP = 11;
265+
266+
/**
267+
* The user has performed a left and down gesture on the touch screen.
268+
*/
269+
public static final int GESTURE_SWIPE_LEFT_AND_DOWN = 12;
270+
271+
/**
272+
* The user has performed a right and up gesture on the touch screen.
273+
*/
274+
public static final int GESTURE_SWIPE_RIGHT_AND_UP = 13;
275+
276+
/**
277+
* The user has performed a right and down gesture on the touch screen.
278+
*/
279+
public static final int GESTURE_SWIPE_RIGHT_AND_DOWN = 14;
280+
281+
/**
282+
* The user has performed an up and left gesture on the touch screen.
283+
*/
284+
public static final int GESTURE_SWIPE_UP_AND_LEFT = 15;
285+
286+
/**
287+
* The user has performed an up and right gesture on the touch screen.
288+
*/
289+
public static final int GESTURE_SWIPE_UP_AND_RIGHT = 16;
290+
291+
/**
292+
* The user has performed an down and left gesture on the touch screen.
293+
*/
294+
public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 17;
295+
296+
/**
297+
* The user has performed an down and right gesture on the touch screen.
298+
*/
299+
public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 18;
300+
261301
/**
262302
* The {@link Intent} that must be declared as handled by the service.
263303
*/
264304
public static final String SERVICE_INTERFACE =
265305
"android.accessibilityservice.AccessibilityService";
266306

267-
private static final int UNDEFINED = -1;
268-
269307
/**
270308
* Name under which an AccessibilityService component publishes information
271309
* about itself. This meta-data must reference an XML resource containing an
@@ -284,6 +322,28 @@ public abstract class AccessibilityService extends Service {
284322
*/
285323
public static final String SERVICE_META_DATA = "android.accessibilityservice";
286324

325+
/**
326+
* Action to go back.
327+
*/
328+
public static final int GLOBAL_ACTION_BACK = 1;
329+
330+
/**
331+
* Action to go home.
332+
*/
333+
public static final int GLOBAL_ACTION_HOME = 2;
334+
335+
/**
336+
* Action to open the recents.
337+
*/
338+
public static final int GLOBAL_ACTION_RECENTS = 3;
339+
340+
/**
341+
* Action to open the notifications.
342+
*/
343+
public static final int GLOBAL_ACTION_NOTIFICATIONS = 4;
344+
345+
private static final int UNDEFINED = -1;
346+
287347
private static final String LOG_TAG = "AccessibilityService";
288348

289349
interface Callbacks {
@@ -344,6 +404,22 @@ protected void onServiceConnected() {
344404
protected void onGesture(int gestureId) {
345405
// TODO: Describe the default gesture processing in the javaDoc once it is finalized.
346406

407+
// Global actions.
408+
switch (gestureId) {
409+
case GESTURE_SWIPE_DOWN_AND_LEFT: {
410+
performGlobalAction(GLOBAL_ACTION_BACK);
411+
} return;
412+
case GESTURE_SWIPE_DOWN_AND_RIGHT: {
413+
performGlobalAction(GLOBAL_ACTION_HOME);
414+
} return;
415+
case GESTURE_SWIPE_UP_AND_LEFT: {
416+
performGlobalAction(GLOBAL_ACTION_RECENTS);
417+
} return;
418+
case GESTURE_SWIPE_UP_AND_RIGHT: {
419+
performGlobalAction(GLOBAL_ACTION_NOTIFICATIONS);
420+
} return;
421+
}
422+
347423
// Cache the id to avoid locking
348424
final int connectionId = mConnectionId;
349425
if (connectionId == UNDEFINED) {
@@ -357,10 +433,12 @@ protected void onGesture(int gestureId) {
357433
if (root == null) {
358434
return;
359435
}
360-
AccessibilityNodeInfo current = root.findFocus(View.FOCUS_ACCESSIBILITY);
436+
AccessibilityNodeInfo current = root.findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
361437
if (current == null) {
362438
current = root;
363439
}
440+
441+
// Local actions.
364442
AccessibilityNodeInfo next = null;
365443
switch (gestureId) {
366444
case GESTURE_SWIPE_UP: {
@@ -401,6 +479,33 @@ protected void onGesture(int gestureId) {
401479
}
402480
}
403481

482+
/**
483+
* Performs a global action. Such an action can be performed
484+
* at any moment regardless of the current application or user
485+
* location in that application. For example going back, going
486+
* home, opening recents, etc.
487+
*
488+
* @param action The action to perform.
489+
* @return Whether the action was successfully performed.
490+
*
491+
* @see #GLOBAL_ACTION_BACK
492+
* @see #GLOBAL_ACTION_HOME
493+
* @see #GLOBAL_ACTION_NOTIFICATIONS
494+
* @see #GLOBAL_ACTION_RECENTS
495+
*/
496+
public final boolean performGlobalAction(int action) {
497+
IAccessibilityServiceConnection connection =
498+
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
499+
if (connection != null) {
500+
try {
501+
return connection.perfromGlobalAction(action);
502+
} catch (RemoteException re) {
503+
Log.w(LOG_TAG, "Error while calling performGlobalAction", re);
504+
}
505+
}
506+
return false;
507+
}
508+
404509
/**
405510
* Gets the an {@link AccessibilityServiceInfo} describing this
406511
* {@link AccessibilityService}. This method is useful if one wants

core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,12 @@ interface IAccessibilityServiceConnection {
160160
* @return The associated accessibility service info.
161161
*/
162162
AccessibilityServiceInfo getServiceInfo();
163+
164+
/**
165+
* Performs a global action, such as going home, going back, etc.
166+
*
167+
* @param action The action to perform.
168+
* @return Whether the action was performed.
169+
*/
170+
boolean perfromGlobalAction(int action);
163171
}

core/java/android/view/AccessibilityInteractionController.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@ final class AccessibilityInteractionController {
5252
private ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
5353
new ArrayList<AccessibilityNodeInfo>();
5454

55-
private final Handler mHandler = new PrivateHandler();
55+
private final Handler mHandler;
5656

5757
private final ViewRootImpl mViewRootImpl;
5858

5959
private final AccessibilityNodePrefetcher mPrefetcher;
6060

6161
public AccessibilityInteractionController(ViewRootImpl viewRootImpl) {
62+
// mView is never null - the caller has already checked.
63+
Looper looper = viewRootImpl.mView.mContext.getMainLooper();
64+
mHandler = new PrivateHandler(looper);
6265
mViewRootImpl = viewRootImpl;
6366
mPrefetcher = new AccessibilityNodePrefetcher();
6467
}
@@ -846,8 +849,8 @@ private class PrivateHandler extends Handler {
846849
private final static int MSG_FIND_FOCUS = 5;
847850
private final static int MSG_FOCUS_SEARCH = 6;
848851

849-
public PrivateHandler() {
850-
super(Looper.getMainLooper());
852+
public PrivateHandler(Looper looper) {
853+
super(looper);
851854
}
852855

853856
@Override

core/java/android/view/View.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6359,16 +6359,14 @@ public void resetAccessibilityStateChanged() {
63596359
public boolean performAccessibilityAction(int action) {
63606360
switch (action) {
63616361
case AccessibilityNodeInfo.ACTION_CLICK: {
6362-
final long now = SystemClock.uptimeMillis();
6363-
// Send down.
6364-
MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
6365-
getWidth() / 2, getHeight() / 2, 0);
6366-
onTouchEvent(event);
6367-
// Send up.
6368-
event.setAction(MotionEvent.ACTION_UP);
6369-
onTouchEvent(event);
6370-
// Clean up.
6371-
event.recycle();
6362+
if (isClickable()) {
6363+
performClick();
6364+
}
6365+
} break;
6366+
case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
6367+
if (isLongClickable()) {
6368+
performLongClick();
6369+
}
63726370
} break;
63736371
case AccessibilityNodeInfo.ACTION_FOCUS: {
63746372
if (!hasFocus()) {

core/java/android/view/ViewGroup.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5792,11 +5792,13 @@ public void recycle() {
57925792
throw new IllegalStateException("Instance already recycled.");
57935793
}
57945794
clear();
5795-
if (sPoolSize < MAX_POOL_SIZE) {
5796-
mNext = sPool;
5797-
mIsPooled = true;
5798-
sPool = this;
5799-
sPoolSize++;
5795+
synchronized (sPoolLock) {
5796+
if (sPoolSize < MAX_POOL_SIZE) {
5797+
mNext = sPool;
5798+
mIsPooled = true;
5799+
sPool = this;
5800+
sPoolSize++;
5801+
}
58005802
}
58015803
}
58025804

@@ -5889,11 +5891,13 @@ public void recycle() {
58895891
throw new IllegalStateException("Instance already recycled.");
58905892
}
58915893
clear();
5892-
if (sPoolSize < MAX_POOL_SIZE) {
5893-
mNext = sPool;
5894-
mIsPooled = true;
5895-
sPool = this;
5896-
sPoolSize++;
5894+
synchronized (sPoolLock) {
5895+
if (sPoolSize < MAX_POOL_SIZE) {
5896+
mNext = sPool;
5897+
mIsPooled = true;
5898+
sPool = this;
5899+
sPoolSize++;
5900+
}
58975901
}
58985902
}
58995903

@@ -5943,9 +5947,9 @@ public int compareTo(ViewLocationHolder another) {
59435947
if (widthDiference != 0) {
59445948
return -widthDiference;
59455949
}
5946-
// Return nondeterministically one of them since we do
5947-
// not want to ignore any views.
5948-
return 1;
5950+
// Just break the tie somehow. The accessibliity ids are unique
5951+
// and stable, hence this is deterministic tie breaking.
5952+
return mView.getAccessibilityViewId() - another.mView.getAccessibilityViewId();
59495953
}
59505954

59515955
private void init(ViewGroup root, View view) {

core/java/android/view/ViewRootImpl.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2665,6 +2665,7 @@ private static void forceLayout(View view) {
26652665
private final static int MSG_PROCESS_INPUT_EVENTS = 19;
26662666
private final static int MSG_DISPATCH_SCREEN_STATE = 20;
26672667
private final static int MSG_INVALIDATE_DISPLAY_LIST = 21;
2668+
private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22;
26682669

26692670
final class ViewRootHandler extends Handler {
26702671
@Override
@@ -2712,6 +2713,8 @@ public String getMessageName(Message message) {
27122713
return "MSG_DISPATCH_SCREEN_STATE";
27132714
case MSG_INVALIDATE_DISPLAY_LIST:
27142715
return "MSG_INVALIDATE_DISPLAY_LIST";
2716+
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
2717+
return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
27152718
}
27162719
return super.getMessageName(message);
27172720
}
@@ -2921,6 +2924,9 @@ public void handleMessage(Message msg) {
29212924
case MSG_INVALIDATE_DISPLAY_LIST: {
29222925
invalidateDisplayLists();
29232926
} break;
2927+
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
2928+
setAccessibilityFocusedHost(null);
2929+
} break;
29242930
}
29252931
}
29262932
}
@@ -5066,7 +5072,7 @@ public void onAccessibilityStateChanged(boolean enabled) {
50665072
}
50675073
} else {
50685074
ensureNoConnection();
5069-
setAccessibilityFocusedHost(null);
5075+
mHandler.obtainMessage(MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST).sendToTarget();
50705076
}
50715077
}
50725078

0 commit comments

Comments
 (0)