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     /** @hide */
AccessibilityGestureEvent( int gestureId, int displayId, @NonNull List<MotionEvent> motionEvents)154     public AccessibilityGestureEvent(
155             int gestureId, int displayId, @NonNull List<MotionEvent> motionEvents) {
156         mGestureId = gestureId;
157         mDisplayId = displayId;
158         mMotionEvents.addAll(motionEvents);
159     }
160 
161     /** @hide */
162     @TestApi
AccessibilityGestureEvent(int gestureId, int displayId)163     public AccessibilityGestureEvent(int gestureId, int displayId) {
164         this(gestureId, displayId, new ArrayList<MotionEvent>());
165     }
166 
AccessibilityGestureEvent(@onNull Parcel parcel)167     private AccessibilityGestureEvent(@NonNull Parcel parcel) {
168         mGestureId = parcel.readInt();
169         mDisplayId = parcel.readInt();
170         ParceledListSlice<MotionEvent> slice = parcel.readParcelable(getClass().getClassLoader());
171         mMotionEvents = slice.getList();
172     }
173 
174     /**
175      * Returns the display id of the received-gesture display, for use with
176      * {@link android.hardware.display.DisplayManager#getDisplay(int)}.
177      *
178      * @return the display id.
179      */
getDisplayId()180     public int getDisplayId() {
181         return mDisplayId;
182     }
183 
184     /**
185      * Returns performed gesture id.
186      *
187      * @return the performed gesture id.
188      *
189      */
getGestureId()190     @GestureId public int getGestureId() {
191         return mGestureId;
192     }
193 
194     /**
195      * Returns the motion events that lead to this gesture.
196      *
197      */
198     @NonNull
getMotionEvents()199     public List<MotionEvent> getMotionEvents() {
200         return mMotionEvents;
201     }
202 
203     @NonNull
204     @Override
toString()205     public String toString() {
206         StringBuilder stringBuilder = new StringBuilder("AccessibilityGestureEvent[");
207         stringBuilder.append("gestureId: ").append(gestureIdToString(mGestureId));
208         stringBuilder.append(", ");
209         stringBuilder.append("displayId: ").append(mDisplayId);
210         stringBuilder.append(", ");
211         stringBuilder.append("Motion Events: [");
212         for (int i = 0; i < mMotionEvents.size(); ++i) {
213             String action = MotionEvent.actionToString(mMotionEvents.get(i).getActionMasked());
214             stringBuilder.append(action);
215             if (i < (mMotionEvents.size() - 1)) {
216                 stringBuilder.append(", ");
217             } else {
218                 stringBuilder.append("]");
219             }
220         }
221         stringBuilder.append(']');
222         return stringBuilder.toString();
223     }
224 
225     /**
226      * Returns a string representation of the specified gesture id.
227      */
228     @NonNull
gestureIdToString(int id)229     public static String gestureIdToString(int id) {
230         switch (id) {
231             case GESTURE_UNKNOWN: return "GESTURE_UNKNOWN";
232             case GESTURE_PASSTHROUGH: return "GESTURE_PASSTHROUGH";
233             case GESTURE_TOUCH_EXPLORATION: return "GESTURE_TOUCH_EXPLORATION";
234             case GESTURE_2_FINGER_SINGLE_TAP: return "GESTURE_2_FINGER_SINGLE_TAP";
235             case GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD:
236                 return "GESTURE_2_FINGER_TRIPLE_TAP_AND_HOLD";
237             case GESTURE_2_FINGER_DOUBLE_TAP: return "GESTURE_2_FINGER_DOUBLE_TAP";
238             case GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD:
239                 return "GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD";
240             case GESTURE_2_FINGER_TRIPLE_TAP: return "GESTURE_2_FINGER_TRIPLE_TAP";
241             case GESTURE_3_FINGER_SINGLE_TAP: return "GESTURE_3_FINGER_SINGLE_TAP";
242             case GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD:
243                 return "GESTURE_3_FINGER_SINGLE_TAP_AND_HOLD";
244             case GESTURE_3_FINGER_DOUBLE_TAP: return "GESTURE_3_FINGER_DOUBLE_TAP";
245             case GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD:
246                 return "GESTURE_3_FINGER_DOUBLE_TAP_AND_HOLD";
247             case GESTURE_3_FINGER_TRIPLE_TAP: return "GESTURE_3_FINGER_TRIPLE_TAP";
248             case GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD:
249                 return "GESTURE_3_FINGER_TRIPLE_TAP_AND_HOLD";
250             case GESTURE_4_FINGER_SINGLE_TAP: return "GESTURE_4_FINGER_SINGLE_TAP";
251             case GESTURE_4_FINGER_DOUBLE_TAP: return "GESTURE_4_FINGER_DOUBLE_TAP";
252             case GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD:
253                 return "GESTURE_4_FINGER_DOUBLE_TAP_AND_HOLD";
254             case GESTURE_4_FINGER_TRIPLE_TAP: return "GESTURE_4_FINGER_TRIPLE_TAP";
255             case GESTURE_DOUBLE_TAP: return "GESTURE_DOUBLE_TAP";
256             case GESTURE_DOUBLE_TAP_AND_HOLD: return "GESTURE_DOUBLE_TAP_AND_HOLD";
257             case GESTURE_SWIPE_DOWN: return "GESTURE_SWIPE_DOWN";
258             case GESTURE_SWIPE_DOWN_AND_LEFT: return "GESTURE_SWIPE_DOWN_AND_LEFT";
259             case GESTURE_SWIPE_DOWN_AND_UP: return "GESTURE_SWIPE_DOWN_AND_UP";
260             case GESTURE_SWIPE_DOWN_AND_RIGHT: return "GESTURE_SWIPE_DOWN_AND_RIGHT";
261             case GESTURE_SWIPE_LEFT: return "GESTURE_SWIPE_LEFT";
262             case GESTURE_SWIPE_LEFT_AND_UP: return "GESTURE_SWIPE_LEFT_AND_UP";
263             case GESTURE_SWIPE_LEFT_AND_RIGHT: return "GESTURE_SWIPE_LEFT_AND_RIGHT";
264             case GESTURE_SWIPE_LEFT_AND_DOWN: return "GESTURE_SWIPE_LEFT_AND_DOWN";
265             case GESTURE_SWIPE_RIGHT: return "GESTURE_SWIPE_RIGHT";
266             case GESTURE_SWIPE_RIGHT_AND_UP: return "GESTURE_SWIPE_RIGHT_AND_UP";
267             case GESTURE_SWIPE_RIGHT_AND_LEFT: return "GESTURE_SWIPE_RIGHT_AND_LEFT";
268             case GESTURE_SWIPE_RIGHT_AND_DOWN: return "GESTURE_SWIPE_RIGHT_AND_DOWN";
269             case GESTURE_SWIPE_UP: return "GESTURE_SWIPE_UP";
270             case GESTURE_SWIPE_UP_AND_LEFT: return "GESTURE_SWIPE_UP_AND_LEFT";
271             case GESTURE_SWIPE_UP_AND_DOWN: return "GESTURE_SWIPE_UP_AND_DOWN";
272             case GESTURE_SWIPE_UP_AND_RIGHT: return "GESTURE_SWIPE_UP_AND_RIGHT";
273             case GESTURE_2_FINGER_SWIPE_DOWN: return "GESTURE_2_FINGER_SWIPE_DOWN";
274             case GESTURE_2_FINGER_SWIPE_LEFT: return "GESTURE_2_FINGER_SWIPE_LEFT";
275             case GESTURE_2_FINGER_SWIPE_RIGHT: return "GESTURE_2_FINGER_SWIPE_RIGHT";
276             case GESTURE_2_FINGER_SWIPE_UP: return "GESTURE_2_FINGER_SWIPE_UP";
277             case GESTURE_3_FINGER_SWIPE_DOWN: return "GESTURE_3_FINGER_SWIPE_DOWN";
278             case GESTURE_3_FINGER_SWIPE_LEFT: return "GESTURE_3_FINGER_SWIPE_LEFT";
279             case GESTURE_3_FINGER_SWIPE_RIGHT: return "GESTURE_3_FINGER_SWIPE_RIGHT";
280             case GESTURE_3_FINGER_SWIPE_UP: return "GESTURE_3_FINGER_SWIPE_UP";
281             case GESTURE_4_FINGER_SWIPE_DOWN: return "GESTURE_4_FINGER_SWIPE_DOWN";
282             case GESTURE_4_FINGER_SWIPE_LEFT: return "GESTURE_4_FINGER_SWIPE_LEFT";
283             case GESTURE_4_FINGER_SWIPE_RIGHT: return "GESTURE_4_FINGER_SWIPE_RIGHT";
284             case GESTURE_4_FINGER_SWIPE_UP: return "GESTURE_4_FINGER_SWIPE_UP";
285             default: return Integer.toHexString(id);
286         }
287     }
288 
289     /**
290      * {@inheritDoc}
291      */
292     @Override
describeContents()293     public int describeContents() {
294         return 0;
295     }
296 
297     @Override
writeToParcel(@onNull Parcel parcel, int flags)298     public void writeToParcel(@NonNull Parcel parcel, int flags) {
299         parcel.writeInt(mGestureId);
300         parcel.writeInt(mDisplayId);
301         parcel.writeParcelable(new ParceledListSlice<MotionEvent>(mMotionEvents), 0);
302     }
303 
304     /**
305      * @see Parcelable.Creator
306      */
307     public static final @NonNull Parcelable.Creator<AccessibilityGestureEvent> CREATOR =
308             new Parcelable.Creator<AccessibilityGestureEvent>() {
309         public AccessibilityGestureEvent createFromParcel(Parcel parcel) {
310             return new AccessibilityGestureEvent(parcel);
311         }
312 
313         public AccessibilityGestureEvent[] newArray(int size) {
314             return new AccessibilityGestureEvent[size];
315         }
316     };
317 
318 }
319