10029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown/*
20029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Copyright (C) 2011 The Android Open Source Project
30029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *
40029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
50029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * you may not use this file except in compliance with the License.
60029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * You may obtain a copy of the License at
70029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *
80029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
90029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *
100029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Unless required by applicable law or agreed to in writing, software
110029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
120029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * See the License for the specific language governing permissions and
140029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * limitations under the License.
150029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown */
160029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
170029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownpackage com.android.server.accessibility;
180029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
190029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.content.Context;
20d1ff736d01cebaee70b76f012b660ae549c252b9Svetoslav Ganovimport android.os.PowerManager;
21545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganovimport android.util.Pools.SimplePool;
220029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.util.Slog;
23545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganovimport android.view.Choreographer;
24152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganovimport android.view.Display;
25736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganovimport android.view.InputDevice;
260029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.InputEvent;
27c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.view.InputFilter;
28c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslavimport android.view.KeyEvent;
290029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.MotionEvent;
300029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.WindowManagerPolicy;
3186783474fdec98a22bc22e224462767eab13e273Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
320029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
33545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov/**
34545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov * This class is an input filter for implementing accessibility features such
35545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov * as display magnification and explore by touch.
36545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov *
37545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov * NOTE: This class has to be created and poked only from the main thread.
38545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov */
391cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganovclass AccessibilityInputFilter extends InputFilter implements EventStreamTransformation {
401cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
411cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    private static final String TAG = AccessibilityInputFilter.class.getSimpleName();
421cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
43736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov    private static final boolean DEBUG = false;
440029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
451cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    /**
461cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * Flag for enabling the screen magnification feature.
471cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     *
481cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * @see #setEnabledFeatures(int)
491cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     */
501cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    static final int FLAG_FEATURE_SCREEN_MAGNIFIER = 0x00000001;
511cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
521cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    /**
531cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * Flag for enabling the touch exploration feature.
541cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     *
551cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     * @see #setEnabledFeatures(int)
561cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov     */
571cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    static final int FLAG_FEATURE_TOUCH_EXPLORATION = 0x00000002;
581cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
59ca523d6e95061f99455589512100839118044d43Svetoslav    /**
60ca523d6e95061f99455589512100839118044d43Svetoslav     * Flag for enabling the filtering key events feature.
61ca523d6e95061f99455589512100839118044d43Svetoslav     *
62ca523d6e95061f99455589512100839118044d43Svetoslav     * @see #setEnabledFeatures(int)
63ca523d6e95061f99455589512100839118044d43Svetoslav     */
64ca523d6e95061f99455589512100839118044d43Svetoslav    static final int FLAG_FEATURE_FILTER_KEY_EVENTS = 0x00000004;
65ca523d6e95061f99455589512100839118044d43Svetoslav
66545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private final Runnable mProcessBatchedEventsRunnable = new Runnable() {
67545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        @Override
68545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        public void run() {
69545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
70545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            if (DEBUG) {
71545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                Slog.i(TAG, "Begin batch processing for frame: " + frameTimeNanos);
72545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            }
73545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            processBatchedEvents(frameTimeNanos);
74545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            if (DEBUG) {
75545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                Slog.i(TAG, "End batch processing.");
76545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            }
77545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            if (mEventQueue != null) {
78545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                scheduleProcessBatchedEvents();
79545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            }
80545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
81545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    };
82545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
830029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    private final Context mContext;
840029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
85d1ff736d01cebaee70b76f012b660ae549c252b9Svetoslav Ganov    private final PowerManager mPm;
86d1ff736d01cebaee70b76f012b660ae549c252b9Svetoslav Ganov
87e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov    private final AccessibilityManagerService mAms;
884213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov
89545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private final Choreographer mChoreographer;
90545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
91c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav    private int mCurrentTouchDeviceId;
92736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov
931cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    private boolean mInstalled;
941cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
951cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    private int mEnabledFeatures;
964213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov
971cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    private TouchExplorer mTouchExplorer;
98213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav
991cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    private ScreenMagnifier mScreenMagnifier;
100213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav
1011cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    private EventStreamTransformation mEventHandler;
102736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov
103545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private MotionEventHolder mEventQueue;
104545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
105213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav    private boolean mMotionEventSequenceStarted;
106213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav
107213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav    private boolean mHoverEventSequenceStarted;
108213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav
109c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav    private boolean mKeyEventSequenceStarted;
110c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav
111ca523d6e95061f99455589512100839118044d43Svetoslav    private boolean mFilterKeyEvents;
112ca523d6e95061f99455589512100839118044d43Svetoslav
1131cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    AccessibilityInputFilter(Context context, AccessibilityManagerService service) {
1140029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        super(context.getMainLooper());
1150029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        mContext = context;
116e15ccb93add99ebb9cd7aec03a04faa37f45b39dSvetoslav Ganov        mAms = service;
1171cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
118545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        mChoreographer = Choreographer.getInstance();
1190029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1200029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1210029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    @Override
1220029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public void onInstalled() {
1230029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        if (DEBUG) {
1240029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            Slog.d(TAG, "Accessibility input filter installed.");
1250029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
1261cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        mInstalled = true;
1271cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        disableFeatures();
1281cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        enableFeatures();
1290029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        super.onInstalled();
1300029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1310029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1320029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    @Override
1330029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public void onUninstalled() {
1340029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        if (DEBUG) {
1350029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            Slog.d(TAG, "Accessibility input filter uninstalled.");
1360029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
1371cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        mInstalled = false;
1381cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        disableFeatures();
1390029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        super.onUninstalled();
1400029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1410029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1420029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    @Override
1430029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public void onInputEvent(InputEvent event, int policyFlags) {
1440029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        if (DEBUG) {
145736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            Slog.d(TAG, "Received event: " + event + ", policyFlags=0x"
146736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov                    + Integer.toHexString(policyFlags));
1470029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
148c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if (event instanceof MotionEvent
149c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav                && event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) {
150c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            MotionEvent motionEvent = (MotionEvent) event;
151c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            onMotionEvent(motionEvent, policyFlags);
152c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        } else if (event instanceof KeyEvent
153c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav                && event.isFromSource(InputDevice.SOURCE_KEYBOARD)) {
154c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            KeyEvent keyEvent = (KeyEvent) event;
155c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            onKeyEvent(keyEvent, policyFlags);
156c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        } else {
1571cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            super.onInputEvent(event, policyFlags);
1581cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
159c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav    }
160c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav
161c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav    private void onMotionEvent(MotionEvent event, int policyFlags) {
162c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if (mEventHandler == null) {
1631cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            super.onInputEvent(event, policyFlags);
1641cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            return;
1651cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
1661cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) {
167213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            mMotionEventSequenceStarted = false;
168213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            mHoverEventSequenceStarted = false;
1691cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mEventHandler.clear();
1701cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            super.onInputEvent(event, policyFlags);
1711cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            return;
1721cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
1731cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        final int deviceId = event.getDeviceId();
174c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if (mCurrentTouchDeviceId != deviceId) {
175c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            mCurrentTouchDeviceId = deviceId;
176213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            mMotionEventSequenceStarted = false;
177213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            mHoverEventSequenceStarted = false;
178213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            mEventHandler.clear();
1791cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
180c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if (mCurrentTouchDeviceId < 0) {
181213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            super.onInputEvent(event, policyFlags);
182213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            return;
183213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        }
184213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        // We do not handle scroll events.
185c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if (event.getActionMasked() == MotionEvent.ACTION_SCROLL) {
186213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            super.onInputEvent(event, policyFlags);
187213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            return;
188213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        }
189213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        // Wait for a down touch event to start processing.
190c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if (event.isTouchEvent()) {
191213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            if (!mMotionEventSequenceStarted) {
192c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav                if (event.getActionMasked() != MotionEvent.ACTION_DOWN) {
193213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav                    return;
194213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav                }
195213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav                mMotionEventSequenceStarted = true;
196213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            }
197213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        } else {
19857bf88508e0491caced22c4c592d33aba6d88129Svetoslav            // Wait for an enter hover event to start processing.
199213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            if (!mHoverEventSequenceStarted) {
200c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav                if (event.getActionMasked() != MotionEvent.ACTION_HOVER_ENTER) {
201213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav                    return;
202213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav                }
203213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav                mHoverEventSequenceStarted = true;
204213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav            }
205213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        }
206545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        batchMotionEvent((MotionEvent) event, policyFlags);
207545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    }
208545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
209c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav    private void onKeyEvent(KeyEvent event, int policyFlags) {
210ca523d6e95061f99455589512100839118044d43Svetoslav        if (!mFilterKeyEvents) {
211ca523d6e95061f99455589512100839118044d43Svetoslav            super.onInputEvent(event, policyFlags);
212ca523d6e95061f99455589512100839118044d43Svetoslav            return;
213ca523d6e95061f99455589512100839118044d43Svetoslav        }
214c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) {
215c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            mKeyEventSequenceStarted = false;
216c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            super.onInputEvent(event, policyFlags);
217c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            return;
218c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        }
219c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        // Wait for a down key event to start processing.
220c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        if (!mKeyEventSequenceStarted) {
221c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            if (event.getAction() != KeyEvent.ACTION_DOWN) {
22283526c181e1dd1cf77c25ee1f47079037dec5dddKristian Monsen                super.onInputEvent(event, policyFlags);
223c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav                return;
224c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            }
225c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav            mKeyEventSequenceStarted = true;
226c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        }
227c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav        mAms.notifyKeyEvent(event, policyFlags);
228c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav    }
229c4fccd183f1bb47a027bb303af5e65bec2f68b1bSvetoslav
230545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private void scheduleProcessBatchedEvents() {
231545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
232545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                mProcessBatchedEventsRunnable, null);
233545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    }
234545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
235545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private void batchMotionEvent(MotionEvent event, int policyFlags) {
236545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        if (DEBUG) {
237545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            Slog.i(TAG, "Batching event: " + event + ", policyFlags: " + policyFlags);
238545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
239545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        if (mEventQueue == null) {
240545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            mEventQueue = MotionEventHolder.obtain(event, policyFlags);
241545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            scheduleProcessBatchedEvents();
242545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            return;
243545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
244545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        if (mEventQueue.event.addBatch(event)) {
245545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            return;
246545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
247545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        MotionEventHolder holder = MotionEventHolder.obtain(event, policyFlags);
248545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        holder.next = mEventQueue;
249545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        mEventQueue.previous = holder;
250545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        mEventQueue = holder;
251545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    }
252545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
253545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private void processBatchedEvents(long frameNanos) {
254545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        MotionEventHolder current = mEventQueue;
255545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        while (current.next != null) {
256545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            current = current.next;
257545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
258545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        while (true) {
259545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            if (current == null) {
260545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                mEventQueue = null;
261545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                break;
262545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            }
263545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            if (current.event.getEventTimeNano() >= frameNanos) {
264545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                // Finished with this choreographer frame. Do the rest on the next one.
265545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                current.next = null;
266545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                break;
267545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            }
268545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            handleMotionEvent(current.event, current.policyFlags);
269545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            MotionEventHolder prior = current;
270545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            current = current.previous;
271545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            prior.recycle();
272545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
273545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    }
274545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
275545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private void handleMotionEvent(MotionEvent event, int policyFlags) {
276545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        if (DEBUG) {
277545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            Slog.i(TAG, "Handling batched event: " + event + ", policyFlags: " + policyFlags);
278545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
27957bf88508e0491caced22c4c592d33aba6d88129Svetoslav        // Since we do batch processing it is possible that by the time the
28057bf88508e0491caced22c4c592d33aba6d88129Svetoslav        // next batch is processed the event handle had been set to null.
28157bf88508e0491caced22c4c592d33aba6d88129Svetoslav        if (mEventHandler != null) {
28257bf88508e0491caced22c4c592d33aba6d88129Svetoslav            mPm.userActivity(event.getEventTime(), false);
28357bf88508e0491caced22c4c592d33aba6d88129Svetoslav            MotionEvent transformedEvent = MotionEvent.obtain(event);
28457bf88508e0491caced22c4c592d33aba6d88129Svetoslav            mEventHandler.onMotionEvent(transformedEvent, event, policyFlags);
28557bf88508e0491caced22c4c592d33aba6d88129Svetoslav            transformedEvent.recycle();
28657bf88508e0491caced22c4c592d33aba6d88129Svetoslav        }
2871cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
2881cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
2891cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    @Override
29045af84a483165f06c04d74baba67f90da29c6ad2Svetoslav Ganov    public void onMotionEvent(MotionEvent transformedEvent, MotionEvent rawEvent,
29145af84a483165f06c04d74baba67f90da29c6ad2Svetoslav Ganov            int policyFlags) {
29245af84a483165f06c04d74baba67f90da29c6ad2Svetoslav Ganov        sendInputEvent(transformedEvent, policyFlags);
2931cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
2941cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
2951cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    @Override
2961cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    public void onAccessibilityEvent(AccessibilityEvent event) {
2971cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        // TODO Implement this to inject the accessibility event
2981cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        //      into the accessibility manager service similarly
2991cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        //      to how this is done for input events.
3001cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3011cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3021cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    @Override
3031cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    public void setNext(EventStreamTransformation sink) {
3041cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        /* do nothing */
3051cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3061cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3071cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    @Override
3081cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    public void clear() {
3091cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        /* do nothing */
3101cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3111cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3121cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    void setEnabledFeatures(int enabledFeatures) {
3131cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if (mEnabledFeatures == enabledFeatures) {
3141cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            return;
3151cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3161cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if (mInstalled) {
3171cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            disableFeatures();
3181cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3191cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        mEnabledFeatures = enabledFeatures;
3201cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if (mInstalled) {
3211cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            enableFeatures();
3221cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3231cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3241cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3251cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    void notifyAccessibilityEvent(AccessibilityEvent event) {
3261cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if (mEventHandler != null) {
3271cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mEventHandler.onAccessibilityEvent(event);
3281cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3291cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3301cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3311cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    private void enableFeatures() {
332213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        mMotionEventSequenceStarted = false;
333213c13aadd5bd4fd3876528f17f179379ca1c1f6Svetoslav        mHoverEventSequenceStarted = false;
3341cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) {
335152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov            mEventHandler = mScreenMagnifier = new ScreenMagnifier(mContext,
336152e9bb81aa5b2ab4637f4b2dae04b3ce89fa891Svetoslav Ganov                    Display.DEFAULT_DISPLAY, mAms);
3371cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mEventHandler.setNext(this);
3381cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3391cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
3401cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mTouchExplorer = new TouchExplorer(mContext, mAms);
3411cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mTouchExplorer.setNext(this);
3421cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            if (mEventHandler != null) {
3431cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov                mEventHandler.setNext(mTouchExplorer);
344736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            } else {
3451cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov                mEventHandler = mTouchExplorer;
346736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            }
3470029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
348ca523d6e95061f99455589512100839118044d43Svetoslav        if ((mEnabledFeatures & FLAG_FEATURE_FILTER_KEY_EVENTS) != 0) {
349ca523d6e95061f99455589512100839118044d43Svetoslav            mFilterKeyEvents = true;
350ca523d6e95061f99455589512100839118044d43Svetoslav        }
3510029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
35286783474fdec98a22bc22e224462767eab13e273Svetoslav Ganov
3533dc75ac65f7bb077fd6afa3a7ad35f5899adf445Svetoslav    void disableFeatures() {
354ee33ad24cdc31ed0d7f99e110e041b0a63c9b0f1Svetoslav Ganov        if (mTouchExplorer != null) {
3551cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mTouchExplorer.clear();
3561cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mTouchExplorer.onDestroy();
3571cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mTouchExplorer = null;
3581cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        }
3591cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        if (mScreenMagnifier != null) {
3601cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mScreenMagnifier.clear();
3611cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mScreenMagnifier.onDestroy();
3621cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov            mScreenMagnifier = null;
363ee33ad24cdc31ed0d7f99e110e041b0a63c9b0f1Svetoslav Ganov        }
3641cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        mEventHandler = null;
365ca523d6e95061f99455589512100839118044d43Svetoslav        mKeyEventSequenceStarted = false;
366ca523d6e95061f99455589512100839118044d43Svetoslav        mMotionEventSequenceStarted = false;
367ca523d6e95061f99455589512100839118044d43Svetoslav        mHoverEventSequenceStarted = false;
368ca523d6e95061f99455589512100839118044d43Svetoslav        mFilterKeyEvents = false;
3691cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    }
3701cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov
3711cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    @Override
3721cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov    public void onDestroy() {
3731cf70bbf96930662cab0e699d70b62865766ff52Svetoslav Ganov        /* ignore */
37486783474fdec98a22bc22e224462767eab13e273Svetoslav Ganov    }
375545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
376545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    private static class MotionEventHolder {
377545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        private static final int MAX_POOL_SIZE = 32;
378545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        private static final SimplePool<MotionEventHolder> sPool =
379545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                new SimplePool<MotionEventHolder>(MAX_POOL_SIZE);
380545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
381545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        public int policyFlags;
382545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        public MotionEvent event;
383545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        public MotionEventHolder next;
384545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        public MotionEventHolder previous;
385545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
386545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        public static MotionEventHolder obtain(MotionEvent event, int policyFlags) {
387545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            MotionEventHolder holder = sPool.acquire();
388545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            if (holder == null) {
389545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov                holder = new MotionEventHolder();
390545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            }
391545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            holder.event = MotionEvent.obtain(event);
392545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            holder.policyFlags = policyFlags;
393545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            return holder;
394545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
395545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov
396545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        public void recycle() {
397545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            event.recycle();
398545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            event = null;
399545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            policyFlags = 0;
400545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            next = null;
401545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            previous = null;
402545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov            sPool.release(this);
403545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov        }
404545252f4fde6fbb70b07e97a120c7d1405758017Svetoslav Ganov    }
4050029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown}
406