1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.accessibilityservice;
18 
19 
20 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP;
21 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD;
22 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SINGLE_TAP;
23 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_DOWN;
24 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_LEFT;
25 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_RIGHT;
26 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_SWIPE_UP;
27 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_TRIPLE_TAP;
28 import static android.accessibilityservice.AccessibilityService.GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD;
29 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP;
30 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD;
31 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP;
32 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD;
33 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN;
34 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_LEFT;
35 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_RIGHT;
36 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_SWIPE_UP;
37 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP;
38 import static android.accessibilityservice.AccessibilityService.GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD;
39 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP;
40 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD;
41 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_SINGLE_TAP;
42 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_SWIPE_DOWN;
43 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_SWIPE_LEFT;
44 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_SWIPE_RIGHT;
45 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_SWIPE_UP;
46 import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_TRIPLE_TAP;
47 import static android.accessibilityservice.AccessibilityService.GESTURE_DOUBLE_TAP;
48 import static android.accessibilityservice.AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD;
49 import static android.accessibilityservice.AccessibilityService.GESTURE_PASSTHROUGH;
50 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN;
51 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT;
52 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT;
53 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_UP;
54 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT;
55 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT_AND_DOWN;
56 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT_AND_RIGHT;
57 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT_AND_UP;
58 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT;
59 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT_AND_DOWN;
60 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT_AND_LEFT;
61 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP;
62 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP;
63 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN;
64 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT;
65 import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT;
66 import static android.accessibilityservice.AccessibilityService.GESTURE_TOUCH_EXPLORATION;
67 import static android.accessibilityservice.AccessibilityService.GESTURE_UNKNOWN;
68 
69 import android.annotation.IntDef;
70 import android.annotation.NonNull;
71 import android.annotation.TestApi;
72 import android.content.pm.ParceledListSlice;
73 import android.os.Parcel;
74 import android.os.Parcelable;
75 import android.view.MotionEvent;
76 
77 import java.lang.annotation.Retention;
78 import java.lang.annotation.RetentionPolicy;
79 import java.util.ArrayList;
80 import java.util.List;
81 
82 /**
83  * This class describes the gesture event including gesture id and which display it happens
84  * on.
85  * <p>
86  * <strong>Note:</strong> Accessibility services setting the
87  * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE}
88  * flag can receive gestures.
89  *
90  * @see AccessibilityService#onGesture(AccessibilityGestureEvent)
91  */
92 
93 public final class AccessibilityGestureEvent implements Parcelable {
94 
95     /** @hide */
96     @IntDef(prefix = { "GESTURE_" }, value = {
97           GESTURE_UNKNOWN,
98           GESTURE_TOUCH_EXPLORATION,
99             GESTURE_2_FINGER_SINGLE_TAP,
100             GESTURE_2_FINGER_DOUBLE_TAP,
101             GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD,
102             GESTURE_2_FINGER_TRIPLE_TAP,
103             GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD,
104             GESTURE_3_FINGER_SINGLE_TAP,
105             GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD,
106             GESTURE_3_FINGER_DOUBLE_TAP,
107             GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD,
108             GESTURE_3_FINGER_TRIPLE_TAP,
109             GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD,
110             GESTURE_DOUBLE_TAP,
111             GESTURE_DOUBLE_TAP_AND_HOLD,
112             GESTURE_SWIPE_UP,
113             GESTURE_SWIPE_UP_AND_LEFT,
114             GESTURE_SWIPE_UP_AND_DOWN,
115             GESTURE_SWIPE_UP_AND_RIGHT,
116             GESTURE_SWIPE_DOWN,
117             GESTURE_SWIPE_DOWN_AND_LEFT,
118             GESTURE_SWIPE_DOWN_AND_UP,
119             GESTURE_SWIPE_DOWN_AND_RIGHT,
120             GESTURE_SWIPE_LEFT,
121             GESTURE_SWIPE_LEFT_AND_UP,
122             GESTURE_SWIPE_LEFT_AND_RIGHT,
123             GESTURE_SWIPE_LEFT_AND_DOWN,
124             GESTURE_SWIPE_RIGHT,
125             GESTURE_SWIPE_RIGHT_AND_UP,
126             GESTURE_SWIPE_RIGHT_AND_LEFT,
127             GESTURE_SWIPE_RIGHT_AND_DOWN,
128             GESTURE_2_FINGER_SWIPE_DOWN,
129             GESTURE_2_FINGER_SWIPE_LEFT,
130             GESTURE_2_FINGER_SWIPE_RIGHT,
131             GESTURE_2_FINGER_SWIPE_UP,
132             GESTURE_3_FINGER_SWIPE_DOWN,
133             GESTURE_3_FINGER_SWIPE_LEFT,
134             GESTURE_3_FINGER_SWIPE_RIGHT,
135             GESTURE_3_FINGER_SWIPE_UP,
136             GESTURE_4_FINGER_DOUBLE_TAP,
137             GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD,
138             GESTURE_4_FINGER_SINGLE_TAP,
139             GESTURE_4_FINGER_SWIPE_DOWN,
140             GESTURE_4_FINGER_SWIPE_LEFT,
141             GESTURE_4_FINGER_SWIPE_RIGHT,
142             GESTURE_4_FINGER_SWIPE_UP,
143             GESTURE_4_FINGER_TRIPLE_TAP
144     })
145     @Retention(RetentionPolicy.SOURCE)
146     public @interface GestureId {}
147 
148     @GestureId
149     private final int mGestureId;
150     private final int mDisplayId;
151     private List<MotionEvent> mMotionEvents = new ArrayList<>();
152 
153 /**
154  * Constructs an AccessibilityGestureEvent to be dispatched to an accessibility service.
155  * @param gestureId the id number of the gesture.
156  * @param displayId the display on which this gesture was performed.
157  * @param motionEvents the motion events that lead to this gesture.
158  */
AccessibilityGestureEvent( int gestureId, int displayId, @NonNull List<MotionEvent> motionEvents)159     public AccessibilityGestureEvent(
160             int gestureId, int displayId, @NonNull List<MotionEvent> motionEvents) {
161         mGestureId = gestureId;
162         mDisplayId = displayId;
163         mMotionEvents.addAll(motionEvents);
164     }
165 
166     /** @hide */
167     @TestApi
AccessibilityGestureEvent(int gestureId, int displayId)168     public AccessibilityGestureEvent(int gestureId, int displayId) {
169         this(gestureId, displayId, new ArrayList<MotionEvent>());
170     }
171 
AccessibilityGestureEvent(@onNull Parcel parcel)172     private AccessibilityGestureEvent(@NonNull Parcel parcel) {
173         mGestureId = parcel.readInt();
174         mDisplayId = parcel.readInt();
175         ParceledListSlice<MotionEvent> slice = parcel.readParcelable(getClass().getClassLoader(), android.content.pm.ParceledListSlice.class);
176         mMotionEvents = slice.getList();
177     }
178 
179     /**
180      * Returns the display id of the received-gesture display, for use with
181      * {@link android.hardware.display.DisplayManager#getDisplay(int)}.
182      *
183      * @return the display id.
184      */
getDisplayId()185     public int getDisplayId() {
186         return mDisplayId;
187     }
188 
189     /**
190      * Returns performed gesture id.
191      *
192      * @return the performed gesture id.
193      *
194      */
getGestureId()195     @GestureId public int getGestureId() {
196         return mGestureId;
197     }
198 
199     /**
200      * Returns the motion events that lead to this gesture.
201      *
202      */
203     @NonNull
getMotionEvents()204     public List<MotionEvent> getMotionEvents() {
205         return mMotionEvents;
206     }
207 
208     @NonNull
209     @Override
toString()210     public String toString() {
211         StringBuilder stringBuilder = new StringBuilder("AccessibilityGestureEvent[");
212         stringBuilder.append("gestureId: ").append(gestureIdToString(mGestureId));
213         stringBuilder.append(", ");
214         stringBuilder.append("displayId: ").append(mDisplayId);
215         stringBuilder.append(", ");
216         stringBuilder.append("Motion Events: [");
217         for (int i = 0; i < mMotionEvents.size(); ++i) {
218             String action = MotionEvent.actionToString(mMotionEvents.get(i).getActionMasked());
219             stringBuilder.append(action);
220             if (i < (mMotionEvents.size() - 1)) {
221                 stringBuilder.append(", ");
222             } else {
223                 stringBuilder.append("]");
224             }
225         }
226         stringBuilder.append(']');
227         return stringBuilder.toString();
228     }
229 
230     /**
231      * Returns a string representation of the specified gesture id.
232      */
233     @NonNull
gestureIdToString(int id)234     public static String gestureIdToString(int id) {
235         switch (id) {
236             case GESTURE_UNKNOWN: return "GESTURE_UNKNOWN";
237             case GESTURE_PASSTHROUGH: return "GESTURE_PASSTHROUGH";
238             case GESTURE_TOUCH_EXPLORATION: return "GESTURE_TOUCH_EXPLORATION";
239             case GESTURE_2_FINGER_SINGLE_TAP: return "GESTURE_2_FINGER_SINGLE_TAP";
240             case GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD:
241                 return "GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD";
242             case GESTURE_2_FINGER_DOUBLE_TAP: return "GESTURE_2_FINGER_DOUBLE_TAP";
243             case GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD:
244                 return "GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD";
245             case GESTURE_2_FINGER_TRIPLE_TAP: return "GESTURE_2_FINGER_TRIPLE_TAP";
246             case GESTURE_3_FINGER_SINGLE_TAP: return "GESTURE_3_FINGER_SINGLE_TAP";
247             case GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD:
248                 return "GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD";
249             case GESTURE_3_FINGER_DOUBLE_TAP: return "GESTURE_3_FINGER_DOUBLE_TAP";
250             case GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD:
251                 return "GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD";
252             case GESTURE_3_FINGER_TRIPLE_TAP: return "GESTURE_3_FINGER_TRIPLE_TAP";
253             case GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD:
254                 return "GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD";
255             case GESTURE_4_FINGER_SINGLE_TAP: return "GESTURE_4_FINGER_SINGLE_TAP";
256             case GESTURE_4_FINGER_DOUBLE_TAP: return "GESTURE_4_FINGER_DOUBLE_TAP";
257             case GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD:
258                 return "GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD";
259             case GESTURE_4_FINGER_TRIPLE_TAP: return "GESTURE_4_FINGER_TRIPLE_TAP";
260             case GESTURE_DOUBLE_TAP: return "GESTURE_DOUBLE_TAP";
261             case GESTURE_DOUBLE_TAP_AND_HOLD: return "GESTURE_DOUBLE_TAP_AND_HOLD";
262             case GESTURE_SWIPE_DOWN: return "GESTURE_SWIPE_DOWN";
263             case GESTURE_SWIPE_DOWN_AND_LEFT: return "GESTURE_SWIPE_DOWN_AND_LEFT";
264             case GESTURE_SWIPE_DOWN_AND_UP: return "GESTURE_SWIPE_DOWN_AND_UP";
265             case GESTURE_SWIPE_DOWN_AND_RIGHT: return "GESTURE_SWIPE_DOWN_AND_RIGHT";
266             case GESTURE_SWIPE_LEFT: return "GESTURE_SWIPE_LEFT";
267             case GESTURE_SWIPE_LEFT_AND_UP: return "GESTURE_SWIPE_LEFT_AND_UP";
268             case GESTURE_SWIPE_LEFT_AND_RIGHT: return "GESTURE_SWIPE_LEFT_AND_RIGHT";
269             case GESTURE_SWIPE_LEFT_AND_DOWN: return "GESTURE_SWIPE_LEFT_AND_DOWN";
270             case GESTURE_SWIPE_RIGHT: return "GESTURE_SWIPE_RIGHT";
271             case GESTURE_SWIPE_RIGHT_AND_UP: return "GESTURE_SWIPE_RIGHT_AND_UP";
272             case GESTURE_SWIPE_RIGHT_AND_LEFT: return "GESTURE_SWIPE_RIGHT_AND_LEFT";
273             case GESTURE_SWIPE_RIGHT_AND_DOWN: return "GESTURE_SWIPE_RIGHT_AND_DOWN";
274             case GESTURE_SWIPE_UP: return "GESTURE_SWIPE_UP";
275             case GESTURE_SWIPE_UP_AND_LEFT: return "GESTURE_SWIPE_UP_AND_LEFT";
276             case GESTURE_SWIPE_UP_AND_DOWN: return "GESTURE_SWIPE_UP_AND_DOWN";
277             case GESTURE_SWIPE_UP_AND_RIGHT: return "GESTURE_SWIPE_UP_AND_RIGHT";
278             case GESTURE_2_FINGER_SWIPE_DOWN: return "GESTURE_2_FINGER_SWIPE_DOWN";
279             case GESTURE_2_FINGER_SWIPE_LEFT: return "GESTURE_2_FINGER_SWIPE_LEFT";
280             case GESTURE_2_FINGER_SWIPE_RIGHT: return "GESTURE_2_FINGER_SWIPE_RIGHT";
281             case GESTURE_2_FINGER_SWIPE_UP: return "GESTURE_2_FINGER_SWIPE_UP";
282             case GESTURE_3_FINGER_SWIPE_DOWN: return "GESTURE_3_FINGER_SWIPE_DOWN";
283             case GESTURE_3_FINGER_SWIPE_LEFT: return "GESTURE_3_FINGER_SWIPE_LEFT";
284             case GESTURE_3_FINGER_SWIPE_RIGHT: return "GESTURE_3_FINGER_SWIPE_RIGHT";
285             case GESTURE_3_FINGER_SWIPE_UP: return "GESTURE_3_FINGER_SWIPE_UP";
286             case GESTURE_4_FINGER_SWIPE_DOWN: return "GESTURE_4_FINGER_SWIPE_DOWN";
287             case GESTURE_4_FINGER_SWIPE_LEFT: return "GESTURE_4_FINGER_SWIPE_LEFT";
288             case GESTURE_4_FINGER_SWIPE_RIGHT: return "GESTURE_4_FINGER_SWIPE_RIGHT";
289             case GESTURE_4_FINGER_SWIPE_UP: return "GESTURE_4_FINGER_SWIPE_UP";
290             default: return Integer.toHexString(id);
291         }
292     }
293 
294     /**
295      * {@inheritDoc}
296      */
297     @Override
describeContents()298     public int describeContents() {
299         return 0;
300     }
301 
302     @Override
writeToParcel(@onNull Parcel parcel, int flags)303     public void writeToParcel(@NonNull Parcel parcel, int flags) {
304         parcel.writeInt(mGestureId);
305         parcel.writeInt(mDisplayId);
306         parcel.writeParcelable(new ParceledListSlice<MotionEvent>(mMotionEvents), 0);
307     }
308 
309     /**
310      * @see Parcelable.Creator
311      */
312     public static final @NonNull Parcelable.Creator<AccessibilityGestureEvent> CREATOR =
313             new Parcelable.Creator<AccessibilityGestureEvent>() {
314         public AccessibilityGestureEvent createFromParcel(Parcel parcel) {
315             return new AccessibilityGestureEvent(parcel);
316         }
317 
318         public AccessibilityGestureEvent[] newArray(int size) {
319             return new AccessibilityGestureEvent[size];
320         }
321     };
322 
323 }
324