Loading services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +18 −217 Original line number Diff line number Diff line Loading @@ -64,21 +64,17 @@ import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.Pools.Pool; import android.util.Pools.SimplePool; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.IWindow; import android.view.InputDevice; import android.view.InputEventConsistencyVerifier; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.WindowInfo; import android.view.WindowManager; import android.view.WindowManagerInternal; import android.view.WindowManagerPolicy; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -146,8 +142,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private static final int OWN_PROCESS_ID = android.os.Process.myPid(); private static final int MAX_POOL_SIZE = 10; private static final int WINDOW_ID_UNKNOWN = -1; private static int sIdCounter = 0; Loading @@ -158,9 +152,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final Object mLock = new Object(); private final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(MAX_POOL_SIZE); private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); Loading Loading @@ -193,6 +184,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private boolean mHasInputFilter; private KeyEventDispatcher mKeyEventDispatcher; private final Set<ComponentName> mTempComponentNameSet = new HashSet<>(); private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList = Loading Loading @@ -756,12 +749,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { boolean notifyKeyEvent(KeyEvent event, int policyFlags) { synchronized (mLock) { KeyEvent localClone = KeyEvent.obtain(event); boolean handled = notifyKeyEventLocked(localClone, policyFlags, false); if (!handled) { handled = notifyKeyEventLocked(localClone, policyFlags, true); List<Service> boundServices = getCurrentUserStateLocked().mBoundServices; if (boundServices.isEmpty()) { return false; } return handled; return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices); } } Loading Loading @@ -935,31 +927,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } private boolean notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault) { // TODO: Now we are giving the key events to the last enabled // service that can handle them Ideally, the user should // make the call which service handles key events. However, // only one service should handle key events to avoid user // frustration when different behavior is observed from // different combinations of enabled accessibility services. UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { Service service = state.mBoundServices.get(i); // Key events are handled only by services that declared // this capability and requested to filter key events. if (!service.mRequestFilterKeyEvents || (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { continue; } if (service.mIsDefault == isDefault) { service.notifyKeyEvent(event, policyFlags); return true; } } return false; } private void notifyClearAccessibilityCacheLocked() { UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { Loading Loading @@ -1754,6 +1721,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return null; } private KeyEventDispatcher getKeyEventDispatcher() { if (mKeyEventDispatcher == null) { mKeyEventDispatcher = new KeyEventDispatcher( mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock); } return mKeyEventDispatcher; } @Override public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP); Loading Loading @@ -1954,22 +1929,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) { PendingEvent pendingEvent = mPendingEventPool.acquire(); if (pendingEvent == null) { pendingEvent = new PendingEvent(); } pendingEvent.event = event; pendingEvent.policyFlags = policyFlags; pendingEvent.sequence = sequence; return pendingEvent; } private void recyclePendingEventLocked(PendingEvent pendingEvent) { pendingEvent.clear(); mPendingEventPool.release(pendingEvent); } private int findWindowIdLocked(IBinder token) { final int globalIndex = mGlobalWindowTokens.indexOfValue(token); if (globalIndex >= 0) { Loading Loading @@ -2082,8 +2041,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>(); final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher(); boolean mWasConnectedAndDied; // Handler only for dispatching accessibility events since we use event Loading Loading @@ -2195,7 +2152,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } UserState userState = getUserStateLocked(mUserId); mKeyEventDispatcher.flush(); getKeyEventDispatcher().flush(this); if (!mIsAutomation) { mContext.unbindService(this); } else { Loading @@ -2212,7 +2169,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public void setOnKeyEventResult(boolean handled, int sequence) { mKeyEventDispatcher.setOnKeyEventResult(handled, sequence); getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); } @Override Loading Loading @@ -2926,7 +2883,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return; } mWasConnectedAndDied = true; mKeyEventDispatcher.flush(); getKeyEventDispatcher().flush(this); UserState userState = getUserStateLocked(mUserId); // The death recipient is unregistered in removeServiceLocked removeServiceLocked(this, userState); Loading Loading @@ -3035,11 +2992,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { gestureId, 0).sendToTarget(); } public void notifyKeyEvent(KeyEvent event, int policyFlags) { mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT, policyFlags, 0, event).sendToTarget(); } public void notifyClearAccessibilityNodeInfoCache() { mInvocationHandler.sendEmptyMessage( InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); Loading Loading @@ -3084,10 +3036,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } private void notifyKeyEventInternal(KeyEvent event, int policyFlags) { mKeyEventDispatcher.notifyKeyEvent(event, policyFlags); } private void notifyClearAccessibilityCacheInternal() { final IAccessibilityServiceClient listener; synchronized (mLock) { Loading Loading @@ -3205,9 +3153,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final class InvocationHandler extends Handler { public static final int MSG_ON_GESTURE = 1; public static final int MSG_ON_KEY_EVENT = 2; public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 3; public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4; public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; Loading @@ -3226,21 +3172,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { notifyGestureInternal(gestureId); } break; case MSG_ON_KEY_EVENT: { KeyEvent event = (KeyEvent) message.obj; final int policyFlags = message.arg1; notifyKeyEventInternal(event, policyFlags); } break; case MSG_CLEAR_ACCESSIBILITY_CACHE: { notifyClearAccessibilityCacheInternal(); } break; case MSG_ON_KEY_EVENT_TIMEOUT: { PendingEvent eventState = (PendingEvent) message.obj; setOnKeyEventResult(false, eventState.sequence); } break; case MSG_ON_MAGNIFICATION_CHANGED: { final SomeArgs args = (SomeArgs) message.obj; final Region region = (Region) args.arg1; Loading Loading @@ -3278,140 +3213,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } private final class KeyEventDispatcher { private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500; private PendingEvent mPendingEvents; private final InputEventConsistencyVerifier mSentEventsVerifier = InputEventConsistencyVerifier.isInstrumentationEnabled() ? new InputEventConsistencyVerifier( this, 0, KeyEventDispatcher.class.getSimpleName()) : null; public void notifyKeyEvent(KeyEvent event, int policyFlags) { final PendingEvent pendingEvent; synchronized (mLock) { pendingEvent = addPendingEventLocked(event, policyFlags); } Message message = mInvocationHandler.obtainMessage( InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS); try { // Accessibility services are exclusively not in the system // process, therefore no need to clone the motion event to // prevent tampering. It will be cloned in the IPC call. mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence); } catch (RemoteException re) { setOnKeyEventResult(false, pendingEvent.sequence); } } public void setOnKeyEventResult(boolean handled, int sequence) { synchronized (mLock) { PendingEvent pendingEvent = removePendingEventLocked(sequence); if (pendingEvent != null) { mInvocationHandler.removeMessages( InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); pendingEvent.handled = handled; finishPendingEventLocked(pendingEvent); } } } public void flush() { synchronized (mLock) { cancelAllPendingEventsLocked(); if (mSentEventsVerifier != null) { mSentEventsVerifier.reset(); } } } private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) { final int sequence = event.getSequenceNumber(); PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence); pendingEvent.next = mPendingEvents; mPendingEvents = pendingEvent; return pendingEvent; } private PendingEvent removePendingEventLocked(int sequence) { PendingEvent previous = null; PendingEvent current = mPendingEvents; while (current != null) { if (current.sequence == sequence) { if (previous != null) { previous.next = current.next; } else { mPendingEvents = current.next; } current.next = null; return current; } previous = current; current = current.next; } return null; } private void finishPendingEventLocked(PendingEvent pendingEvent) { if (!pendingEvent.handled) { sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags); } // Nullify the event since we do not want it to be // recycled yet. It will be sent to the input filter. pendingEvent.event = null; recyclePendingEventLocked(pendingEvent); } private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) { if (DEBUG) { Slog.i(LOG_TAG, "Injecting event: " + event); } if (mSentEventsVerifier != null) { mSentEventsVerifier.onKeyEvent(event, 0); } policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER; mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, policyFlags, 0, event).sendToTarget(); } private void cancelAllPendingEventsLocked() { while (mPendingEvents != null) { PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence); pendingEvent.handled = false; mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); finishPendingEventLocked(pendingEvent); } } } } private static final class PendingEvent { PendingEvent next; KeyEvent event; int policyFlags; int sequence; boolean handled; public void clear() { if (event != null) { event.recycle(); event = null; } next = null; policyFlags = 0; sequence = 0; handled = false; } } final class WindowsForAccessibilityCallback implements Loading services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java 0 → 100644 +285 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +18 −217 Original line number Diff line number Diff line Loading @@ -64,21 +64,17 @@ import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.Pools.Pool; import android.util.Pools.SimplePool; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.IWindow; import android.view.InputDevice; import android.view.InputEventConsistencyVerifier; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.WindowInfo; import android.view.WindowManager; import android.view.WindowManagerInternal; import android.view.WindowManagerPolicy; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -146,8 +142,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private static final int OWN_PROCESS_ID = android.os.Process.myPid(); private static final int MAX_POOL_SIZE = 10; private static final int WINDOW_ID_UNKNOWN = -1; private static int sIdCounter = 0; Loading @@ -158,9 +152,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final Object mLock = new Object(); private final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(MAX_POOL_SIZE); private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); Loading Loading @@ -193,6 +184,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private boolean mHasInputFilter; private KeyEventDispatcher mKeyEventDispatcher; private final Set<ComponentName> mTempComponentNameSet = new HashSet<>(); private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList = Loading Loading @@ -756,12 +749,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { boolean notifyKeyEvent(KeyEvent event, int policyFlags) { synchronized (mLock) { KeyEvent localClone = KeyEvent.obtain(event); boolean handled = notifyKeyEventLocked(localClone, policyFlags, false); if (!handled) { handled = notifyKeyEventLocked(localClone, policyFlags, true); List<Service> boundServices = getCurrentUserStateLocked().mBoundServices; if (boundServices.isEmpty()) { return false; } return handled; return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices); } } Loading Loading @@ -935,31 +927,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } private boolean notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault) { // TODO: Now we are giving the key events to the last enabled // service that can handle them Ideally, the user should // make the call which service handles key events. However, // only one service should handle key events to avoid user // frustration when different behavior is observed from // different combinations of enabled accessibility services. UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { Service service = state.mBoundServices.get(i); // Key events are handled only by services that declared // this capability and requested to filter key events. if (!service.mRequestFilterKeyEvents || (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { continue; } if (service.mIsDefault == isDefault) { service.notifyKeyEvent(event, policyFlags); return true; } } return false; } private void notifyClearAccessibilityCacheLocked() { UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { Loading Loading @@ -1754,6 +1721,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return null; } private KeyEventDispatcher getKeyEventDispatcher() { if (mKeyEventDispatcher == null) { mKeyEventDispatcher = new KeyEventDispatcher( mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock); } return mKeyEventDispatcher; } @Override public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP); Loading Loading @@ -1954,22 +1929,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) { PendingEvent pendingEvent = mPendingEventPool.acquire(); if (pendingEvent == null) { pendingEvent = new PendingEvent(); } pendingEvent.event = event; pendingEvent.policyFlags = policyFlags; pendingEvent.sequence = sequence; return pendingEvent; } private void recyclePendingEventLocked(PendingEvent pendingEvent) { pendingEvent.clear(); mPendingEventPool.release(pendingEvent); } private int findWindowIdLocked(IBinder token) { final int globalIndex = mGlobalWindowTokens.indexOfValue(token); if (globalIndex >= 0) { Loading Loading @@ -2082,8 +2041,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>(); final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher(); boolean mWasConnectedAndDied; // Handler only for dispatching accessibility events since we use event Loading Loading @@ -2195,7 +2152,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } UserState userState = getUserStateLocked(mUserId); mKeyEventDispatcher.flush(); getKeyEventDispatcher().flush(this); if (!mIsAutomation) { mContext.unbindService(this); } else { Loading @@ -2212,7 +2169,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public void setOnKeyEventResult(boolean handled, int sequence) { mKeyEventDispatcher.setOnKeyEventResult(handled, sequence); getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); } @Override Loading Loading @@ -2926,7 +2883,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return; } mWasConnectedAndDied = true; mKeyEventDispatcher.flush(); getKeyEventDispatcher().flush(this); UserState userState = getUserStateLocked(mUserId); // The death recipient is unregistered in removeServiceLocked removeServiceLocked(this, userState); Loading Loading @@ -3035,11 +2992,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { gestureId, 0).sendToTarget(); } public void notifyKeyEvent(KeyEvent event, int policyFlags) { mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT, policyFlags, 0, event).sendToTarget(); } public void notifyClearAccessibilityNodeInfoCache() { mInvocationHandler.sendEmptyMessage( InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); Loading Loading @@ -3084,10 +3036,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } private void notifyKeyEventInternal(KeyEvent event, int policyFlags) { mKeyEventDispatcher.notifyKeyEvent(event, policyFlags); } private void notifyClearAccessibilityCacheInternal() { final IAccessibilityServiceClient listener; synchronized (mLock) { Loading Loading @@ -3205,9 +3153,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final class InvocationHandler extends Handler { public static final int MSG_ON_GESTURE = 1; public static final int MSG_ON_KEY_EVENT = 2; public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 3; public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4; public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; Loading @@ -3226,21 +3172,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { notifyGestureInternal(gestureId); } break; case MSG_ON_KEY_EVENT: { KeyEvent event = (KeyEvent) message.obj; final int policyFlags = message.arg1; notifyKeyEventInternal(event, policyFlags); } break; case MSG_CLEAR_ACCESSIBILITY_CACHE: { notifyClearAccessibilityCacheInternal(); } break; case MSG_ON_KEY_EVENT_TIMEOUT: { PendingEvent eventState = (PendingEvent) message.obj; setOnKeyEventResult(false, eventState.sequence); } break; case MSG_ON_MAGNIFICATION_CHANGED: { final SomeArgs args = (SomeArgs) message.obj; final Region region = (Region) args.arg1; Loading Loading @@ -3278,140 +3213,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } private final class KeyEventDispatcher { private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500; private PendingEvent mPendingEvents; private final InputEventConsistencyVerifier mSentEventsVerifier = InputEventConsistencyVerifier.isInstrumentationEnabled() ? new InputEventConsistencyVerifier( this, 0, KeyEventDispatcher.class.getSimpleName()) : null; public void notifyKeyEvent(KeyEvent event, int policyFlags) { final PendingEvent pendingEvent; synchronized (mLock) { pendingEvent = addPendingEventLocked(event, policyFlags); } Message message = mInvocationHandler.obtainMessage( InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS); try { // Accessibility services are exclusively not in the system // process, therefore no need to clone the motion event to // prevent tampering. It will be cloned in the IPC call. mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence); } catch (RemoteException re) { setOnKeyEventResult(false, pendingEvent.sequence); } } public void setOnKeyEventResult(boolean handled, int sequence) { synchronized (mLock) { PendingEvent pendingEvent = removePendingEventLocked(sequence); if (pendingEvent != null) { mInvocationHandler.removeMessages( InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); pendingEvent.handled = handled; finishPendingEventLocked(pendingEvent); } } } public void flush() { synchronized (mLock) { cancelAllPendingEventsLocked(); if (mSentEventsVerifier != null) { mSentEventsVerifier.reset(); } } } private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) { final int sequence = event.getSequenceNumber(); PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence); pendingEvent.next = mPendingEvents; mPendingEvents = pendingEvent; return pendingEvent; } private PendingEvent removePendingEventLocked(int sequence) { PendingEvent previous = null; PendingEvent current = mPendingEvents; while (current != null) { if (current.sequence == sequence) { if (previous != null) { previous.next = current.next; } else { mPendingEvents = current.next; } current.next = null; return current; } previous = current; current = current.next; } return null; } private void finishPendingEventLocked(PendingEvent pendingEvent) { if (!pendingEvent.handled) { sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags); } // Nullify the event since we do not want it to be // recycled yet. It will be sent to the input filter. pendingEvent.event = null; recyclePendingEventLocked(pendingEvent); } private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) { if (DEBUG) { Slog.i(LOG_TAG, "Injecting event: " + event); } if (mSentEventsVerifier != null) { mSentEventsVerifier.onKeyEvent(event, 0); } policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER; mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, policyFlags, 0, event).sendToTarget(); } private void cancelAllPendingEventsLocked() { while (mPendingEvents != null) { PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence); pendingEvent.handled = false; mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent); finishPendingEventLocked(pendingEvent); } } } } private static final class PendingEvent { PendingEvent next; KeyEvent event; int policyFlags; int sequence; boolean handled; public void clear() { if (event != null) { event.recycle(); event = null; } next = null; policyFlags = 0; sequence = 0; handled = false; } } final class WindowsForAccessibilityCallback implements Loading
services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java 0 → 100644 +285 −0 File added.Preview size limit exceeded, changes collapsed. Show changes