Merge "Add API to record touch interactions."
This commit is contained in:
@@ -2851,6 +2851,7 @@ package android.accessibilityservice {
|
||||
method public int describeContents();
|
||||
method public int getDisplayId();
|
||||
method public int getGestureId();
|
||||
method @NonNull public java.util.List<android.view.MotionEvent> getMotionEvents();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.AccessibilityGestureEvent> CREATOR;
|
||||
}
|
||||
@@ -2932,6 +2933,7 @@ package android.accessibilityservice {
|
||||
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_RIGHT = 14; // 0xe
|
||||
field public static final int GESTURE_UNKNOWN = 0; // 0x0
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS = 14; // 0xe
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON = 11; // 0xb
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON_CHOOSER = 12; // 0xc
|
||||
@@ -3047,6 +3049,7 @@ package android.accessibilityservice {
|
||||
field public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1024; // 0x400
|
||||
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
|
||||
field public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 64; // 0x40
|
||||
field public static final int FLAG_SEND_MOTION_EVENTS = 16384; // 0x4000
|
||||
field public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 2048; // 0x800
|
||||
field public int eventTypes;
|
||||
field public int feedbackType;
|
||||
|
||||
@@ -46,6 +46,7 @@ import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_TRIPLE_TAP;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_DOUBLE_TAP;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_PASSTHROUGH;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT;
|
||||
@@ -62,15 +63,21 @@ import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_TOUCH_EXPLORATION;
|
||||
import static android.accessibilityservice.AccessibilityService.GESTURE_UNKNOWN;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class describes the gesture event including gesture id and which display it happens
|
||||
@@ -87,6 +94,8 @@ public final class AccessibilityGestureEvent implements Parcelable {
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "GESTURE_" }, value = {
|
||||
GESTURE_UNKNOWN,
|
||||
GESTURE_TOUCH_EXPLORATION,
|
||||
GESTURE_2_FINGER_SINGLE_TAP,
|
||||
GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD,
|
||||
GESTURE_2_FINGER_DOUBLE_TAP,
|
||||
@@ -139,17 +148,27 @@ public final class AccessibilityGestureEvent implements Parcelable {
|
||||
@GestureId
|
||||
private final int mGestureId;
|
||||
private final int mDisplayId;
|
||||
private List<MotionEvent> mMotionEvents = new ArrayList<>();
|
||||
|
||||
/** @hide */
|
||||
public AccessibilityGestureEvent(
|
||||
int gestureId, int displayId, @NonNull List<MotionEvent> motionEvents) {
|
||||
mGestureId = gestureId;
|
||||
mDisplayId = displayId;
|
||||
mMotionEvents.addAll(motionEvents);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@TestApi
|
||||
public AccessibilityGestureEvent(int gestureId, int displayId) {
|
||||
mGestureId = gestureId;
|
||||
mDisplayId = displayId;
|
||||
this(gestureId, displayId, new ArrayList<MotionEvent>());
|
||||
}
|
||||
|
||||
private AccessibilityGestureEvent(@NonNull Parcel parcel) {
|
||||
mGestureId = parcel.readInt();
|
||||
mDisplayId = parcel.readInt();
|
||||
ParceledListSlice<MotionEvent> slice = parcel.readParcelable(getClass().getClassLoader());
|
||||
mMotionEvents = slice.getList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,6 +191,15 @@ public final class AccessibilityGestureEvent implements Parcelable {
|
||||
return mGestureId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the motion events that lead to this gesture.
|
||||
*
|
||||
*/
|
||||
@NonNull
|
||||
public List<MotionEvent> getMotionEvents() {
|
||||
return mMotionEvents;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -179,12 +207,26 @@ public final class AccessibilityGestureEvent implements Parcelable {
|
||||
stringBuilder.append("gestureId: ").append(eventTypeToString(mGestureId));
|
||||
stringBuilder.append(", ");
|
||||
stringBuilder.append("displayId: ").append(mDisplayId);
|
||||
stringBuilder.append(", ");
|
||||
stringBuilder.append("Motion Events: [");
|
||||
for (int i = 0; i < mMotionEvents.size(); ++i) {
|
||||
String action = MotionEvent.actionToString(mMotionEvents.get(i).getActionMasked());
|
||||
stringBuilder.append(action);
|
||||
if (i < (mMotionEvents.size() - 1)) {
|
||||
stringBuilder.append(", ");
|
||||
} else {
|
||||
stringBuilder.append("]");
|
||||
}
|
||||
}
|
||||
stringBuilder.append(']');
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
private static String eventTypeToString(int eventType) {
|
||||
switch (eventType) {
|
||||
case GESTURE_UNKNOWN: return "GESTURE_UNKNOWN";
|
||||
case GESTURE_PASSTHROUGH: return "GESTURE_PASSTHROUGH";
|
||||
case GESTURE_TOUCH_EXPLORATION: return "GESTURE_TOUCH_EXPLORATION";
|
||||
case GESTURE_2_FINGER_SINGLE_TAP: return "GESTURE_2_FINGER_SINGLE_TAP";
|
||||
case GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD:
|
||||
return "GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD";
|
||||
@@ -252,6 +294,7 @@ public final class AccessibilityGestureEvent implements Parcelable {
|
||||
public void writeToParcel(@NonNull Parcel parcel, int flags) {
|
||||
parcel.writeInt(mGestureId);
|
||||
parcel.writeInt(mDisplayId);
|
||||
parcel.writeParcelable(new ParceledListSlice<MotionEvent>(mMotionEvents), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -234,6 +234,29 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public abstract class AccessibilityService extends Service {
|
||||
|
||||
/**
|
||||
* The user has performed a touch-exploration gesture on the touch screen without ever
|
||||
* triggering gesture detection. This gesture is only dispatched when {@link
|
||||
* AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int GESTURE_TOUCH_EXPLORATION = -2;
|
||||
|
||||
/**
|
||||
* The user has performed a passthrough gesture on the touch screen without ever triggering
|
||||
* gesture detection. This gesture is only dispatched when {@link
|
||||
* AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
|
||||
* @hide
|
||||
*/
|
||||
public static final int GESTURE_PASSTHROUGH = -1;
|
||||
|
||||
/**
|
||||
* The user has performed an unrecognized gesture on the touch screen. This gesture is only
|
||||
* dispatched when {@link AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
|
||||
*/
|
||||
public static final int GESTURE_UNKNOWN = 0;
|
||||
|
||||
/**
|
||||
* The user has performed a swipe up gesture on the touch screen.
|
||||
*/
|
||||
|
||||
@@ -376,6 +376,20 @@ public class AccessibilityServiceInfo implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x0002000;
|
||||
|
||||
/**
|
||||
* This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, a
|
||||
* service will receive the motion events for each successfully-detected gesture. The service
|
||||
* will also receive an AccessibilityGestureEvent of type GESTURE_INVALID for each cancelled
|
||||
* gesture along with its motion events. A service will receive a gesture of type
|
||||
* GESTURE_PASSTHROUGH and accompanying motion events for every passthrough gesture that does
|
||||
* not start gesture detection. This information can be used to collect instances of improper
|
||||
* gesture detection behavior and relay that information to framework developers. If {@link
|
||||
* #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this flag has no effect.
|
||||
*
|
||||
* @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
|
||||
*/
|
||||
public static final int FLAG_SEND_MOTION_EVENTS = 0x0004000;
|
||||
|
||||
/** {@hide} */
|
||||
public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
|
||||
|
||||
@@ -1276,6 +1290,8 @@ public class AccessibilityServiceInfo implements Parcelable {
|
||||
return "FLAG_REQUEST_MULTI_FINGER_GESTURES";
|
||||
case FLAG_REQUEST_2_FINGER_PASSTHROUGH:
|
||||
return "FLAG_REQUEST_2_FINGER_PASSTHROUGH";
|
||||
case FLAG_SEND_MOTION_EVENTS:
|
||||
return "FLAG_SEND_MOTION_EVENTS";
|
||||
case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
|
||||
return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
|
||||
case FLAG_REPORT_VIEW_IDS:
|
||||
|
||||
@@ -3748,6 +3748,7 @@
|
||||
<flag name="flagServiceHandlesDoubleTap" value="0x00000800" />
|
||||
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_MULTI_FINGER_GESTURES}. -->
|
||||
<flag name="flagRequestMultiFingerGestures" value="0x00001000" />
|
||||
<flag name="flagSendMotionEvents" value="0x0004000" />
|
||||
</attr>
|
||||
<!-- Component name of an activity that allows the user to modify
|
||||
the settings for this service. This setting cannot be changed at runtime. -->
|
||||
|
||||
@@ -2851,6 +2851,7 @@ package android.accessibilityservice {
|
||||
method public int describeContents();
|
||||
method public int getDisplayId();
|
||||
method public int getGestureId();
|
||||
method @NonNull public java.util.List<android.view.MotionEvent> getMotionEvents();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.AccessibilityGestureEvent> CREATOR;
|
||||
}
|
||||
@@ -2932,6 +2933,7 @@ package android.accessibilityservice {
|
||||
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_RIGHT = 14; // 0xe
|
||||
field public static final int GESTURE_UNKNOWN = 0; // 0x0
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS = 14; // 0xe
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON = 11; // 0xb
|
||||
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON_CHOOSER = 12; // 0xc
|
||||
@@ -3047,6 +3049,7 @@ package android.accessibilityservice {
|
||||
field public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1024; // 0x400
|
||||
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
|
||||
field public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 64; // 0x40
|
||||
field public static final int FLAG_SEND_MOTION_EVENTS = 16384; // 0x4000
|
||||
field public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 2048; // 0x800
|
||||
field public int eventTypes;
|
||||
field public int feedbackType;
|
||||
|
||||
@@ -150,6 +150,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
|
||||
private boolean mRequestTwoFingerPassthrough;
|
||||
|
||||
private boolean mSendMotionEvents;
|
||||
|
||||
boolean mRequestFilterKeyEvents;
|
||||
|
||||
boolean mRetrieveInteractiveWindows;
|
||||
@@ -329,6 +331,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
& AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0;
|
||||
mRequestTwoFingerPassthrough =
|
||||
(info.flags & AccessibilityServiceInfo.FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0;
|
||||
mSendMotionEvents =
|
||||
(info.flags & AccessibilityServiceInfo.FLAG_SEND_MOTION_EVENTS) != 0;
|
||||
mRequestFilterKeyEvents =
|
||||
(info.flags & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
|
||||
mRetrieveInteractiveWindows = (info.flags
|
||||
@@ -1780,6 +1784,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
return mRequestTwoFingerPassthrough;
|
||||
}
|
||||
|
||||
public boolean isSendMotionEventsEnabled() {
|
||||
return mSendMotionEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
|
||||
mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
|
||||
|
||||
@@ -119,12 +119,19 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
|
||||
static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000100;
|
||||
|
||||
/**
|
||||
* Flag for enabling multi-finger gestures.
|
||||
* Flag for enabling two-finger passthrough when multi-finger gestures are enabled.
|
||||
*
|
||||
* @see #setUserAndEnabledFeatures(int, int)
|
||||
*/
|
||||
static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x00000200;
|
||||
|
||||
/**
|
||||
* Flag for including motion events when dispatching a gesture.
|
||||
*
|
||||
* @see #setUserAndEnabledFeatures(int, int)
|
||||
*/
|
||||
static final int FLAG_SEND_MOTION_EVENTS = 0x00000400;
|
||||
|
||||
static final int FEATURES_AFFECTING_MOTION_EVENTS =
|
||||
FLAG_FEATURE_INJECT_MOTION_EVENTS
|
||||
| FLAG_FEATURE_AUTOCLICK
|
||||
@@ -432,6 +439,9 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
|
||||
if ((mEnabledFeatures & FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0) {
|
||||
explorer.setTwoFingerPassthroughEnabled(true);
|
||||
}
|
||||
if ((mEnabledFeatures & FLAG_SEND_MOTION_EVENTS) != 0) {
|
||||
explorer.setSendMotionEventsEnabled(true);
|
||||
}
|
||||
addFirstEventHandler(displayId, explorer);
|
||||
mTouchExplorer.put(displayId, explorer);
|
||||
}
|
||||
|
||||
@@ -1867,6 +1867,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
if (userState.isFilterKeyEventsEnabledLocked()) {
|
||||
flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
|
||||
}
|
||||
if (userState.isSendMotionEventsEnabled()) {
|
||||
flags |= AccessibilityInputFilter.FLAG_SEND_MOTION_EVENTS;
|
||||
}
|
||||
|
||||
if (userState.isAutoclickEnabledLocked()) {
|
||||
flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK;
|
||||
}
|
||||
@@ -2147,6 +2151,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
boolean serviceHandlesDoubleTapEnabled = false;
|
||||
boolean requestMultiFingerGestures = false;
|
||||
boolean requestTwoFingerPassthrough = false;
|
||||
boolean sendMotionEvents = false;
|
||||
final int serviceCount = userState.mBoundServices.size();
|
||||
for (int i = 0; i < serviceCount; i++) {
|
||||
AccessibilityServiceConnection service = userState.mBoundServices.get(i);
|
||||
@@ -2155,6 +2160,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
serviceHandlesDoubleTapEnabled = service.isServiceHandlesDoubleTapEnabled();
|
||||
requestMultiFingerGestures = service.isMultiFingerGesturesEnabled();
|
||||
requestTwoFingerPassthrough = service.isTwoFingerPassthroughEnabled();
|
||||
sendMotionEvents = service.isSendMotionEventsEnabled();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2172,6 +2178,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
userState.setServiceHandlesDoubleTapLocked(serviceHandlesDoubleTapEnabled);
|
||||
userState.setMultiFingerGesturesLocked(requestMultiFingerGestures);
|
||||
userState.setTwoFingerPassthroughLocked(requestTwoFingerPassthrough);
|
||||
userState.setSendMotionEventsEnabled(sendMotionEvents);
|
||||
}
|
||||
|
||||
private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) {
|
||||
|
||||
@@ -111,6 +111,7 @@ class AccessibilityUserState {
|
||||
private boolean mServiceHandlesDoubleTap;
|
||||
private boolean mRequestMultiFingerGestures;
|
||||
private boolean mRequestTwoFingerPassthrough;
|
||||
private boolean mSendMotionEventsEnabled;
|
||||
private int mUserInteractiveUiTimeout;
|
||||
private int mUserNonInteractiveUiTimeout;
|
||||
private int mNonInteractiveUiTimeout = 0;
|
||||
@@ -171,6 +172,7 @@ class AccessibilityUserState {
|
||||
mServiceHandlesDoubleTap = false;
|
||||
mRequestMultiFingerGestures = false;
|
||||
mRequestTwoFingerPassthrough = false;
|
||||
mSendMotionEventsEnabled = false;
|
||||
mIsDisplayMagnificationEnabled = false;
|
||||
mIsAutoclickEnabled = false;
|
||||
mUserNonInteractiveUiTimeout = 0;
|
||||
@@ -460,6 +462,7 @@ class AccessibilityUserState {
|
||||
.append(String.valueOf(mRequestMultiFingerGestures));
|
||||
pw.append(", requestTwoFingerPassthrough=")
|
||||
.append(String.valueOf(mRequestTwoFingerPassthrough));
|
||||
pw.append(", sendMotionEventsEnabled").append(String.valueOf(mSendMotionEventsEnabled));
|
||||
pw.append(", displayMagnificationEnabled=").append(String.valueOf(
|
||||
mIsDisplayMagnificationEnabled));
|
||||
pw.append(", autoclickEnabled=").append(String.valueOf(mIsAutoclickEnabled));
|
||||
@@ -802,6 +805,13 @@ class AccessibilityUserState {
|
||||
mRequestTwoFingerPassthrough = enabled;
|
||||
}
|
||||
|
||||
public boolean isSendMotionEventsEnabled() {
|
||||
return mSendMotionEventsEnabled;
|
||||
}
|
||||
|
||||
public void setSendMotionEventsEnabled(boolean mode) {
|
||||
mSendMotionEventsEnabled = mode;
|
||||
}
|
||||
|
||||
public int getUserInteractiveUiTimeoutLocked() {
|
||||
return mUserInteractiveUiTimeout;
|
||||
|
||||
@@ -99,11 +99,15 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
|
||||
boolean mMultiFingerGesturesEnabled;
|
||||
// Whether the two-finger passthrough is enabled when multi-finger gestures are enabled.
|
||||
private boolean mTwoFingerPassthroughEnabled;
|
||||
// Whether to send the motion events during gesture dispatch.
|
||||
private boolean mSendMotionEventsEnabled = false;
|
||||
// A list of all the multi-finger gestures, for easy adding and removal.
|
||||
private final List<GestureMatcher> mMultiFingerGestures = new ArrayList<>();
|
||||
// A list of two-finger swipes, for easy adding and removal when turning on or off two-finger
|
||||
// passthrough.
|
||||
private final List<GestureMatcher> mTwoFingerSwipes = new ArrayList<>();
|
||||
// The list of motion events for the current gesture.
|
||||
private List<MotionEvent> mEvents = new ArrayList<>();
|
||||
// Shared state information.
|
||||
private TouchState mState;
|
||||
|
||||
@@ -230,6 +234,9 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (mSendMotionEventsEnabled) {
|
||||
mEvents.add(MotionEvent.obtainNoHistory(rawEvent));
|
||||
}
|
||||
for (GestureMatcher matcher : mGestures) {
|
||||
if (matcher.getState() != GestureMatcher.STATE_GESTURE_CANCELED) {
|
||||
if (DEBUG) {
|
||||
@@ -240,9 +247,8 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
|
||||
Slog.d(LOG_TAG, matcher.toString());
|
||||
}
|
||||
if (matcher.getState() == GestureMatcher.STATE_GESTURE_COMPLETED) {
|
||||
// Here we just clear and return. The actual gesture dispatch is done in
|
||||
// Here we just return. The actual gesture dispatch is done in
|
||||
// onStateChanged().
|
||||
clear();
|
||||
// No need to process this event any further.
|
||||
return true;
|
||||
}
|
||||
@@ -255,6 +261,11 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
|
||||
for (GestureMatcher matcher : mGestures) {
|
||||
matcher.clear();
|
||||
}
|
||||
if (mEvents != null) {
|
||||
while (mEvents.size() > 0) {
|
||||
mEvents.remove(0).recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -340,29 +351,28 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
|
||||
case GESTURE_DOUBLE_TAP:
|
||||
if (mServiceHandlesDoubleTap) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(gestureId, event.getDisplayId());
|
||||
new AccessibilityGestureEvent(gestureId, event.getDisplayId(), mEvents);
|
||||
mListener.onGestureCompleted(gestureEvent);
|
||||
} else {
|
||||
mListener.onDoubleTap(event, rawEvent, policyFlags);
|
||||
}
|
||||
clear();
|
||||
break;
|
||||
case GESTURE_DOUBLE_TAP_AND_HOLD:
|
||||
if (mServiceHandlesDoubleTap) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(gestureId, event.getDisplayId());
|
||||
new AccessibilityGestureEvent(gestureId, event.getDisplayId(), mEvents);
|
||||
mListener.onGestureCompleted(gestureEvent);
|
||||
} else {
|
||||
mListener.onDoubleTapAndHold(event, rawEvent, policyFlags);
|
||||
}
|
||||
clear();
|
||||
break;
|
||||
default:
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(gestureId, event.getDisplayId());
|
||||
new AccessibilityGestureEvent(gestureId, event.getDisplayId(), mEvents);
|
||||
mListener.onGestureCompleted(gestureEvent);
|
||||
break;
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
public boolean isMultiFingerGesturesEnabled() {
|
||||
@@ -406,4 +416,25 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
|
||||
public boolean isServiceHandlesDoubleTapEnabled() {
|
||||
return mServiceHandlesDoubleTap;
|
||||
}
|
||||
|
||||
public void setSendMotionEventsEnabled(boolean mode) {
|
||||
mSendMotionEventsEnabled = mode;
|
||||
if (!mode) {
|
||||
while (mEvents.size() > 0) {
|
||||
mEvents.remove(0).recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSendMotionEventsEnabled() {
|
||||
return mSendMotionEventsEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current list of motion events. It is the caller's responsibility to copy the list
|
||||
* if they want it to persist after a call to clear().
|
||||
*/
|
||||
public List<MotionEvent> getMotionEvents() {
|
||||
return mEvents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
|
||||
import static com.android.server.accessibility.gestures.TouchState.ALL_POINTER_ID_BITS;
|
||||
|
||||
import android.accessibilityservice.AccessibilityGestureEvent;
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.graphics.Region;
|
||||
@@ -340,6 +341,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
public void onDoubleTapAndHold(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
|
||||
if (mDispatcher.longPressWithTouchEvents(event, policyFlags)) {
|
||||
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD,
|
||||
event.getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
mState.startDelegating();
|
||||
}
|
||||
}
|
||||
@@ -350,7 +359,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
// Remove pending event deliveries.
|
||||
mSendHoverEnterAndMoveDelayed.cancel();
|
||||
mSendHoverExitDelayed.cancel();
|
||||
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_DOUBLE_TAP,
|
||||
event.getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
if (mSendTouchExplorationEndDelayed.isPending()) {
|
||||
mSendTouchExplorationEndDelayed.forceSendAndRemove();
|
||||
}
|
||||
@@ -385,6 +401,9 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
|
||||
@Override
|
||||
public boolean onGestureCompleted(AccessibilityGestureEvent gestureEvent) {
|
||||
if (DEBUG) {
|
||||
Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
|
||||
}
|
||||
endGestureDetection(true);
|
||||
mSendTouchInteractionEndDelayed.cancel();
|
||||
mAms.onGesture(gestureEvent);
|
||||
@@ -411,12 +430,24 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
mDispatcher.sendMotionEvent(
|
||||
event,
|
||||
ACTION_HOVER_MOVE,
|
||||
mState.getLastReceivedEvent(),
|
||||
event,
|
||||
pointerIdBits,
|
||||
policyFlags);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
// Send a gesture with motion events to represent the cancelled gesture.
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_UNKNOWN,
|
||||
event.getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
if (DEBUG) {
|
||||
Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
|
||||
}
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -620,6 +651,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
if (isDraggingGesture(event)) {
|
||||
// Two pointers moving in the same direction within
|
||||
// a given distance perform a drag.
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_PASSTHROUGH,
|
||||
event.getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
computeDraggingPointerIdIfNeeded(event);
|
||||
pointerIdBits = 1 << mDraggingPointerId;
|
||||
event.setEdgeFlags(mReceivedPointerTracker.getLastReceivedDownEdgeFlags());
|
||||
@@ -636,6 +675,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
mState.startDragging();
|
||||
} else {
|
||||
// Two pointers moving arbitrary are delegated to the view hierarchy.
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_PASSTHROUGH,
|
||||
event.getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
mState.startDelegating();
|
||||
mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
|
||||
}
|
||||
@@ -650,6 +697,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
if (DEBUG) {
|
||||
Slog.d(LOG_TAG, "Three-finger edge swipe detected.");
|
||||
}
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_PASSTHROUGH,
|
||||
event.getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
mState.startDelegating();
|
||||
if (mState.isTouchExploring()) {
|
||||
mDispatcher.sendDownForAllNotInjectedPointers(event,
|
||||
@@ -663,6 +718,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
}
|
||||
} else {
|
||||
// More than two pointers are delegated to the view hierarchy.
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_PASSTHROUGH,
|
||||
event.getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
mState.startDelegating();
|
||||
event = MotionEvent.obtainNoHistory(event);
|
||||
mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
|
||||
@@ -1109,6 +1172,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
public void setTwoFingerPassthroughEnabled(boolean enabled) {
|
||||
mGestureDetector.setTwoFingerPassthroughEnabled(enabled);
|
||||
}
|
||||
|
||||
public void setGestureDetectionPassthroughRegion(Region region) {
|
||||
mGestureDetectionPassthroughRegion = region;
|
||||
}
|
||||
@@ -1117,6 +1181,17 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
mTouchExplorationPassthroughRegion = region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to send the motion events that make up each gesture to the accessibility service.
|
||||
*/
|
||||
public void setSendMotionEventsEnabled(boolean mode) {
|
||||
mGestureDetector.setSendMotionEventsEnabled(mode);
|
||||
}
|
||||
|
||||
public boolean isSendMotionEventsEnabled() {
|
||||
return mGestureDetector.isSendMotionEventsEnabled();
|
||||
}
|
||||
|
||||
private boolean shouldPerformGestureDetection(MotionEvent event) {
|
||||
if (mState.isDelegating()) {
|
||||
return false;
|
||||
@@ -1213,7 +1288,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
public void run() {
|
||||
// Send an accessibility event to announce the touch exploration start.
|
||||
mDispatcher.sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
|
||||
|
||||
if (isSendMotionEventsEnabled()) {
|
||||
AccessibilityGestureEvent gestureEvent =
|
||||
new AccessibilityGestureEvent(
|
||||
AccessibilityService.GESTURE_TOUCH_EXPLORATION,
|
||||
mState.getLastReceivedEvent().getDisplayId(),
|
||||
mGestureDetector.getMotionEvents());
|
||||
mAms.onGesture(gestureEvent);
|
||||
}
|
||||
if (!mEvents.isEmpty() && !mRawEvents.isEmpty()) {
|
||||
// Deliver a down event.
|
||||
mDispatcher.sendMotionEvent(mEvents.get(0), ACTION_HOVER_ENTER,
|
||||
|
||||
Reference in New Issue
Block a user