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