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