Input系统学习----AccessibilityService 的dispatchGesture注入点击方法的调用流程(InputFilter)

AccessibilityService 的dispatchGesture方法可以注入触控事件来进行模拟操作,

Github上有个不错的例子,通过识别面部移动来注入点击事件,https://github.com/cmauri/eva_facial_mouse

dispatchGesture的处理流程是怎样的呢,这里粗略查看一下,

AccessibilityService.java


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

onMotionEvent方法,

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 {

MotionEventInjectorsuper.onMotionEvent方法为什么调到AccessibilityInputFilter.javaonMotionEvent方法里了呢?

这个过程比较晦涩,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.javaenableFeatures()方法中,有对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传给mMotionEventInjectorsetNext方法。

所以前面MotionEventInjectorsuper.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,在这个流程中串起来了。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要使用自己封装的axios提交,你需要在Vue组件中引入axios,并将axios传递给vue-upload-component的upload方法的第二个参数,示例代码如下: ``` <template> <div> <vue-upload-component ref="upload" :action="uploadUrl" :headers="uploadHeaders" :data="uploadData" :multiple="false" :accept="'image/*'" @input-filter="inputFilter" @start="handleStart" @progress="handleProgress" @success="handleSuccess" @error="handleError" @abort="handleAbort" ></vue-upload-component> </div> </template> <script> import axios from 'axios' import VueUploadComponent from 'vue-upload-component' export default { components: { VueUploadComponent }, data() { return { uploadUrl: 'your-upload-url', uploadHeaders: { Authorization: 'Bearer ' + localStorage.getItem('token') }, uploadData: {} } }, methods: { inputFilter(newFile, oldFile, prevent) { // your input filter logic }, handleStart() { // handle start event }, handleProgress(event, file, progress) { // handle progress event }, handleSuccess(response, file) { // handle success event }, handleError(response, file) { // handle error event }, handleAbort(file) { // handle abort event }, upload(file) { this.$refs.upload.upload(file, { http: axios, // pass your axios instance here headers: this.uploadHeaders, data: this.uploadData }) } } } </script> ``` 在upload方法中,我们通过this.$refs.upload.upload(file, options)调用vue-upload-component的upload方法,并将自己封装的axios实例作为options对象的http属性传递给vue-upload-component。这样vue-upload-component就会使用我们自己封装的axios实例进行文件上传了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值