AccessibilityService 的dispatchGesture方法可以注入触控事件来进行模拟操作,
Github上有个不错的例子,通过识别面部移动来注入点击事件,https://github.com/cmauri/eva_facial_mouse
dispatchGesture的处理流程是怎样的呢,这里粗略查看一下,
664 public final boolean dispatchGesture(@NonNull GestureDescription gesture,
665 @Nullable GestureResultCallback callback,
666 @Nullable Handler handler) {
686 connection.sendGesture(mGestureStatusCallbackSequence,
687 new ParceledListSlice<>(steps));
frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
353 public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
354 synchronized (mLock) {
355 if (mSecurityPolicy.canPerformGestures(this)) {
356 MotionEventInjector motionEventInjector =
357 mSystemSupport.getMotionEventInjectorLocked();
358 if (motionEventInjector != null) {
359 motionEventInjector.injectEvents(
360 gestureSteps.getList(), mServiceInterface, sequence);
361 } else {
362 try {
363 mServiceInterface.onPerformGestureResult(sequence, false);
364 } catch (RemoteException re) {
365 Slog.e(LOG_TAG, "Error sending motion event injection failure to "
366 + mServiceInterface, re);
367 }
368 }
frameworks/base/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
这个注释值得注意,injectEvents调用会cancel之前的手势
94 /**
95 * Schedule a gesture for injection. The gesture is defined by a set of {@code GestureStep}s,
96 * from which {@code MotionEvent}s will be derived. All gestures currently in progress will be
97 * cancelled.
98 *
99 * @param gestureSteps The gesture steps to inject.
100 * @param serviceInterface The interface to call back with a result when the gesture is
101 * either complete or cancelled.
102 */
103 public void injectEvents(List<GestureStep> gestureSteps,
104 IAccessibilityServiceClient serviceInterface, int sequence) {
105 SomeArgs args = SomeArgs.obtain();
106 args.arg1 = gestureSteps;
107 args.arg2 = serviceInterface;
108 args.argi1 = sequence;
109 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_INJECT_EVENTS, args));
110 }
调用到
136 public boolean handleMessage(Message message) {
137 if (message.what == MESSAGE_INJECT_EVENTS) {
138 SomeArgs args = (SomeArgs) message.obj;
139 injectEventsMainThread((List<GestureStep>) args.arg1,
140 (IAccessibilityServiceClient) args.arg2, args.argi1);
141 args.recycle();
142 return true;
143 }
158 private void injectEventsMainThread(List<GestureStep> gestureSteps,
159 IAccessibilityServiceClient serviceInterface, int sequence) {
201 for (int i = 0; i < events.size(); i++) {
202 MotionEvent event = events.get(i);
203 int isEndOfSequence = (i == events.size() - 1) ? 1 : 0;
204 Message message = mHandler.obtainMessage(
205 MESSAGE_SEND_MOTION_EVENT, isEndOfSequence, 0, event);
206 mLastScheduledEventTime = event.getEventTime();
207 mHandler.sendMessageDelayed(message, Math.max(0, event.getEventTime() - currentTime));
208 }
查看MESSAGE_SEND_MOTION_EVENT
的处理
136 public boolean handleMessage(Message message) {
137 if (message.what == MESSAGE_INJECT_EVENTS) {
138 SomeArgs args = (SomeArgs) message.obj;
139 injectEventsMainThread((List<GestureStep>) args.arg1,
140 (IAccessibilityServiceClient) args.arg2, args.argi1);
141 args.recycle();
142 return true;
143 }
144 if (message.what != MESSAGE_SEND_MOTION_EVENT) {
145 Slog.e(LOG_TAG, "Unknown message: " + message.what);
146 return false;
147 }
148 MotionEvent motionEvent = (MotionEvent) message.obj;
149 sendMotionEventToNext(motionEvent, motionEvent, WindowManagerPolicy.FLAG_PASS_TO_USER);
150 boolean isEndOfSequence = message.arg1 != 0;
151 if (isEndOfSequence) {
152 notifyService(mServiceInterfaceForCurrentGesture, mSequencesInProgress.get(0), true);
153 mSequencesInProgress.remove(0);
154 }
155 return true;
156 }
279
280 private void sendMotionEventToNext(MotionEvent event, MotionEvent rawEvent,
281 int policyFlags) {
282 if (getNext() != null) {
283 super.onMotionEvent(event, rawEvent, policyFlags);
284 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
285 mOpenGesturesInProgress.put(event.getSource(), true);
286 }
287 if ((event.getActionMasked() == MotionEvent.ACTION_UP)
288 || (event.getActionMasked() == MotionEvent.ACTION_CANCEL)) {
289 mOpenGesturesInProgress.put(event.getSource(), false);
290 }
291 }
292 }
这里的super.onMotionEvent 调用到AccessibilityInputFilter.java的
353 public void onMotionEvent(MotionEvent transformedEvent, MotionEvent rawEvent,
354 int policyFlags) {
355 sendInputEvent(transformedEvent, policyFlags);
356 }
因为AccessibilityInputFilter extends InputFilter,所以其sendInputEvent方法实现了事件的注入。
class AccessibilityInputFilter extends InputFilter implements EventStreamTransformation {
MotionEventInjector的super.onMotionEvent方法为什么调到AccessibilityInputFilter.java的onMotionEvent方法里了呢?
这个过程比较晦涩,super.onMotionEvent方法调用其父类BaseEventStreamTransformation的同名方法,
public class MotionEventInjector extends BaseEventStreamTransformation implements Handler.Callback {
BaseEventStreamTransformation是个抽象类,实现的接口EventStreamTransformation类里有onMotionEvent方法的定义,
19abstract class BaseEventStreamTransformation implements EventStreamTransformation {
20 private EventStreamTransformation mNext;
21
22 @Override
23 public void setNext(EventStreamTransformation next) {
24 mNext = next;
25 }
26
27 @Override
28 public EventStreamTransformation getNext() {
29 return mNext;
30 }
31}
frameworks/base/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java
68 default void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
69 EventStreamTransformation next = getNext();
70 if (next != null) {
71 next.onMotionEvent(event, rawEvent, policyFlags);
72 }
73 }
调用next.onMotionEvent方法,
next是什么呢,回到motionEventInjector定义的地方,
frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
353 public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
354 synchronized (mLock) {
355 if (mSecurityPolicy.canPerformGestures(this)) {
356 MotionEventInjector motionEventInjector =
357 mSystemSupport.getMotionEventInjectorLocked();
其赋值来自
mSystemSupport.getMotionEventInjectorLocked()
AccessibilityManagerService.java
951 public MotionEventInjector getMotionEventInjectorLocked() {
952 final long endMillis = SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS;
953 while ((mMotionEventInjector == null) && (SystemClock.uptimeMillis() < endMillis)) {
954 try {
955 mLock.wait(endMillis - SystemClock.uptimeMillis());
956 } catch (InterruptedException ie) {
957 /* ignore */
958 }
959 }
960 if (mMotionEventInjector == null) {
961 Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
962 }
963 return mMotionEventInjector;
964 }
这个mMotionEventInjector是在哪里new的呢,在AccessibilityManagerService.java里只有一个赋值的地方,
在AccessibilityManagerService.java里
936 /**
937 * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector.
938 * Not using a getter because the AccessibilityInputFilter isn't thread-safe
939 *
940 * @param motionEventInjector The new value of the motionEventInjector. May be null.
941 */
942 void setMotionEventInjector(MotionEventInjector motionEventInjector) {
943 synchronized (mLock) {
944 mMotionEventInjector = motionEventInjector;
945 // We may be waiting on this object being set
946 mLock.notifyAll();
947 }
948 }
从注释可以看到,这个方法是在AccessibilityInputFilter里调用的
class AccessibilityInputFilter extends InputFilter implements EventStreamTransformation {
在AccessibilityInputFilter.java的enableFeatures()方法中,有对mMotionEventInjector的关联操作,
415 private void enableFeatures() {
443 if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
444 mMotionEventInjector = new MotionEventInjector(mContext.getMainLooper());
445 addFirstEventHandler(mMotionEventInjector);
446 mAms.setMotionEventInjector(mMotionEventInjector);
447 }
addFirstEventHandler(mMotionEventInjector);
里面
462 private void addFirstEventHandler(EventStreamTransformation handler) {
463 if (mEventHandler != null) {
464 handler.setNext(mEventHandler);
465 } else {
466 handler.setNext(this);
467 }
468 mEventHandler = handler;
469 }
把this传给mMotionEventInjector的setNext方法。
所以前面MotionEventInjector的super.onMotionEvent方法调用到这里,实现了事件的注入
353 public void onMotionEvent(MotionEvent transformedEvent, MotionEvent rawEvent,
354 int policyFlags) {
355 sendInputEvent(transformedEvent, policyFlags);
356 }
关于sendInputEvent的注入,可以参考
https://zhuanlan.zhihu.com/p/31195334
可以看到,从AccessibilityService到AccessibilityManagerService.java, 以及里面使用的AccessibilityInputFilter,在这个流程中串起来了。