1a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver/*
2a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * Copyright (C) 2015 The Android Open Source Project
3a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver *
4a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * Licensed under the Apache License, Version 2.0 (the "License");
5a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * you may not use this file except in compliance with the License.
6a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * You may obtain a copy of the License at
7a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver *
8a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver *      http://www.apache.org/licenses/LICENSE-2.0
9a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver *
10a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * Unless required by applicable law or agreed to in writing, software
11a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * distributed under the License is distributed on an "AS IS" BASIS,
12a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * See the License for the specific language governing permissions and
14a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * limitations under the License.
15a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver */
16a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
17a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverpackage com.android.server.accessibility;
18a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
19a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.accessibilityservice.IAccessibilityServiceClient;
20a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.os.Handler;
21a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.os.Looper;
22a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.os.Message;
23a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.os.RemoteException;
24a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.os.SystemClock;
25a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.util.Slog;
26a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.util.SparseArray;
27a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.view.InputDevice;
28a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.view.KeyEvent;
29a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.view.MotionEvent;
30a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.view.WindowManagerPolicy;
31a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport android.view.accessibility.AccessibilityEvent;
32a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport com.android.internal.os.SomeArgs;
33a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport com.android.server.accessibility.AccessibilityManagerService.Service;
34a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
35a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverimport java.util.List;
36a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
37a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver/**
38a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * Injects MotionEvents to permit {@code AccessibilityService}s to touch the screen on behalf of
39a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * users.
40a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver *
41a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver * All methods except {@code injectEvents} must be called only from the main thread.
42a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver */
43a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaverpublic class MotionEventInjector implements EventStreamTransformation {
44a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private static final String LOG_TAG = "MotionEventInjector";
45a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private static final int MESSAGE_SEND_MOTION_EVENT = 1;
46a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private static final int MESSAGE_INJECT_EVENTS = 2;
47a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private static final int MAX_POINTERS = 11; // Non-binding maximum
48a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
49a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private final Handler mHandler;
50a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private final SparseArray<Boolean> mOpenGesturesInProgress = new SparseArray<>();
51a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
52a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    // These two arrays must be the same length
53a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private MotionEvent.PointerProperties[] mPointerProperties =
54a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            new MotionEvent.PointerProperties[MAX_POINTERS];
55a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private MotionEvent.PointerCoords[] mPointerCoords =
56a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            new MotionEvent.PointerCoords[MAX_POINTERS];
57a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private EventStreamTransformation mNext;
58a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private IAccessibilityServiceClient mServiceInterfaceForCurrentGesture;
59a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private int mSequenceForCurrentGesture;
60a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private int mSourceOfInjectedGesture = InputDevice.SOURCE_UNKNOWN;
61a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private boolean mIsDestroyed = false;
62a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
63a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    /**
64a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     * @param looper A looper on the main thread to use for dispatching new events
65a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     */
66a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public MotionEventInjector(Looper looper) {
67a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        mHandler = new Handler(looper, new Callback());
68a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
69a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
70a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    /**
71a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     * Schedule a series of events for injection. These events must comprise a complete, valid
72a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     * sequence. All gestures currently in progress will be cancelled, and all {@code downTime}
73a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     * and {@code eventTime} fields will be offset by the current time.
74a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     *
75a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     * @param events The events to inject. Must all be from the same source.
76a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     * @param serviceInterface The interface to call back with a result when the gesture is
77a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     * either complete or cancelled.
78a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver     */
79a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public void injectEvents(List<MotionEvent> events,
80a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            IAccessibilityServiceClient serviceInterface, int sequence) {
81a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        SomeArgs args = SomeArgs.obtain();
82a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        args.arg1 = events;
83a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        args.arg2 = serviceInterface;
84a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        args.argi1 = sequence;
85a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_INJECT_EVENTS, args));
86a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
87a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
88a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    @Override
89a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
90a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        cancelAnyPendingInjectedEvents();
91a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        sendMotionEventToNext(event, rawEvent, policyFlags);
92a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
93a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
94a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    @Override
95a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public void onKeyEvent(KeyEvent event, int policyFlags) {
96a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if (mNext != null) {
97a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            mNext.onKeyEvent(event, policyFlags);
98a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
99a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
100a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
101a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    @Override
102a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public void onAccessibilityEvent(AccessibilityEvent event) {
103a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if (mNext != null) {
104a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            mNext.onAccessibilityEvent(event);
105a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
106a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
107a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
108a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    @Override
109a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public void setNext(EventStreamTransformation next) {
110a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        mNext = next;
111a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
112a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
113a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    @Override
114a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public void clearEvents(int inputSource) {
115a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        /*
116a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver         * Reset state for motion events passing through so we won't send a cancel event for
117a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver         * them.
118a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver         */
119a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
120a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            mOpenGesturesInProgress.put(inputSource, false);
121a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
122a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
123a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
124a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    @Override
125a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    public void onDestroy() {
126a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        cancelAnyPendingInjectedEvents();
127a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        mIsDestroyed = true;
128a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
129a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
130a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private void injectEventsMainThread(List<MotionEvent> events,
131a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            IAccessibilityServiceClient serviceInterface, int sequence) {
132a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if (mIsDestroyed) {
133a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            try {
134a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                serviceInterface.onPerformGestureResult(sequence, false);
135a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            } catch (RemoteException re) {
136a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                Slog.e(LOG_TAG, "Error sending status with mIsDestroyed to " + serviceInterface,
137a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                        re);
138a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
139a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            return;
140a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
141a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        cancelAnyPendingInjectedEvents();
142a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        mSourceOfInjectedGesture = events.get(0).getSource();
143a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        cancelAnyGestureInProgress(mSourceOfInjectedGesture);
144a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        mServiceInterfaceForCurrentGesture = serviceInterface;
145a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        mSequenceForCurrentGesture = sequence;
146a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if (mNext == null) {
147a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            notifyService(false);
148a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            return;
149a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
150a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
151a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        long startTime = SystemClock.uptimeMillis();
152a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        for (int i = 0; i < events.size(); i++) {
153a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            MotionEvent event = events.get(i);
154a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            int numPointers = event.getPointerCount();
155a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            if (numPointers > mPointerCoords.length) {
156a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                mPointerCoords = new MotionEvent.PointerCoords[numPointers];
157a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                mPointerProperties = new MotionEvent.PointerProperties[numPointers];
158a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
159a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            for (int j = 0; j < numPointers; j++) {
160a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                if (mPointerCoords[j] == null) {
161a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    mPointerCoords[j] = new MotionEvent.PointerCoords();
162a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    mPointerProperties[j] = new MotionEvent.PointerProperties();
163a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                }
164a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                event.getPointerCoords(j, mPointerCoords[j]);
165a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                event.getPointerProperties(j, mPointerProperties[j]);
166a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
167a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
168a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            /*
169a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver             * MotionEvent doesn't have a setEventTime() method (it carries around history data,
170a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver             * which could become inconsistent), so we need to obtain a new one.
171a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver             */
172a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            MotionEvent offsetEvent = MotionEvent.obtain(startTime + event.getDownTime(),
173a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    startTime + event.getEventTime(), event.getAction(), numPointers,
174a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    mPointerProperties, mPointerCoords, event.getMetaState(),
175a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    event.getButtonState(), event.getXPrecision(), event.getYPrecision(),
176a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    event.getDeviceId(), event.getEdgeFlags(), event.getSource(),
177a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    event.getFlags());
178a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            Message message = mHandler.obtainMessage(MESSAGE_SEND_MOTION_EVENT, offsetEvent);
179a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            mHandler.sendMessageDelayed(message, event.getEventTime());
180a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
181a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
182a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
183a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private void sendMotionEventToNext(MotionEvent event, MotionEvent rawEvent,
184a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            int policyFlags) {
185a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if (mNext != null) {
186a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            mNext.onMotionEvent(event, rawEvent, policyFlags);
187a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
188a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                mOpenGesturesInProgress.put(event.getSource(), true);
189a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
190a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            if ((event.getActionMasked() == MotionEvent.ACTION_UP)
191a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    || (event.getActionMasked() == MotionEvent.ACTION_CANCEL)) {
192a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                mOpenGesturesInProgress.put(event.getSource(), false);
193a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
194a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
195a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
196a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
197a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private void cancelAnyGestureInProgress(int source) {
198a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if ((mNext != null) && mOpenGesturesInProgress.get(source, false)) {
199a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            long now = SystemClock.uptimeMillis();
200a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            MotionEvent cancelEvent =
201a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
202a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            sendMotionEventToNext(cancelEvent, cancelEvent,
203a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    WindowManagerPolicy.FLAG_PASS_TO_USER);
204a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
205a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
206a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
207a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private void cancelAnyPendingInjectedEvents() {
208a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        if (mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
209a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            cancelAnyGestureInProgress(mSourceOfInjectedGesture);
210a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            mHandler.removeMessages(MESSAGE_SEND_MOTION_EVENT);
211a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            notifyService(false);
212a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
213a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
214a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
215a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
216a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private void notifyService(boolean success) {
217a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        try {
218a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            mServiceInterfaceForCurrentGesture.onPerformGestureResult(
219a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    mSequenceForCurrentGesture, success);
220a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        } catch (RemoteException re) {
221a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            Slog.e(LOG_TAG, "Error sending motion event injection status to "
222a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    + mServiceInterfaceForCurrentGesture, re);
223a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
224a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
225a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver
226a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    private class Callback implements Handler.Callback {
227a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        @Override
228a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        public boolean handleMessage(Message message) {
229a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            if (message.what == MESSAGE_INJECT_EVENTS) {
230a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                SomeArgs args = (SomeArgs) message.obj;
231a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                injectEventsMainThread((List<MotionEvent>) args.arg1,
232a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                        (IAccessibilityServiceClient) args.arg2, args.argi1);
233a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                args.recycle();
234a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                return true;
235a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
236a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            if (message.what != MESSAGE_SEND_MOTION_EVENT) {
237a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                throw new IllegalArgumentException("Unknown message: " + message.what);
238a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
239a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            MotionEvent motionEvent = (MotionEvent) message.obj;
240a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            sendMotionEventToNext(motionEvent, motionEvent,
241a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                    WindowManagerPolicy.FLAG_PASS_TO_USER);
242a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            // If the message queue is now empty, then this gesture is complete
243a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
244a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver                notifyService(true);
245a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            }
246a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver            return true;
247a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver        }
248a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver    }
249a6b64f5099b7be6e8384958d8bcddb97bb06ec93Phil Weaver}
250