diff options
| author | David van Tonder <david.vantonder@gmail.com> | 2013-05-16 06:56:44 -0700 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2013-05-16 06:56:44 -0700 |
| commit | 0043015c0dc6400f47edd4124b1dfb5881be3c8a (patch) | |
| tree | f8122f83c0a3f2c05c5b25eb1908c12bf7d014f2 /services/java/com/android/server/input/InputManagerService.java | |
| parent | ab9f90cc32396c51d1ba1e8e9d7852a664936ff9 (diff) | |
| parent | d4bb3bc99c6ba13f7fd7738926aba3e6524d1419 (diff) | |
| download | frameworks_base-0043015c0dc6400f47edd4124b1dfb5881be3c8a.zip frameworks_base-0043015c0dc6400f47edd4124b1dfb5881be3c8a.tar.gz frameworks_base-0043015c0dc6400f47edd4124b1dfb5881be3c8a.tar.bz2 | |
Merge changes I352f1980,I6a4a4635 into cm-10.1
* changes:
Pie controls: A new way of activation
Pie controls: Introducing a pie delivery service
Diffstat (limited to 'services/java/com/android/server/input/InputManagerService.java')
| -rw-r--r-- | services/java/com/android/server/input/InputManagerService.java | 136 |
1 files changed, 109 insertions, 27 deletions
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index 9921b5c..aa3b283 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -97,6 +97,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor, DisplayManagerService.InputManagerFuncs { static final String TAG = "InputManager"; static final boolean DEBUG = false; + static final boolean DEBUG_FILTER = false; private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; @@ -143,8 +144,9 @@ public class InputManagerService extends IInputManager.Stub // State for the currently installed input filter. final Object mInputFilterLock = new Object(); - IInputFilter mInputFilter; // guarded by mInputFilterLock - InputFilterHost mInputFilterHost; // guarded by mInputFilterLock + ChainedInputFilterHost mInputFilterHost; // guarded by mInputFilterLock + ArrayList<ChainedInputFilterHost> mInputFilterChain = + new ArrayList<ChainedInputFilterHost>(); // guarded by mInputFilterLock private static native int nativeInit(InputManagerService service, Context context, MessageQueue messageQueue); @@ -475,34 +477,77 @@ public class InputManagerService extends IInputManager.Stub */ public void setInputFilter(IInputFilter filter) { synchronized (mInputFilterLock) { - final IInputFilter oldFilter = mInputFilter; + final IInputFilter oldFilter = mInputFilterHost != null + ? mInputFilterHost.mInputFilter : null; if (oldFilter == filter) { return; // nothing to do } if (oldFilter != null) { - mInputFilter = null; mInputFilterHost.disconnectLocked(); + mInputFilterChain.remove(mInputFilterHost); mInputFilterHost = null; - try { - oldFilter.uninstall(); - } catch (RemoteException re) { - /* ignore */ - } } if (filter != null) { - mInputFilter = filter; - mInputFilterHost = new InputFilterHost(); - try { - filter.install(mInputFilterHost); - } catch (RemoteException re) { - /* ignore */ + ChainedInputFilterHost head = mInputFilterChain.isEmpty() ? null : + mInputFilterChain.get(0); + mInputFilterHost = new ChainedInputFilterHost(filter, head); + mInputFilterHost.connectLocked(); + mInputFilterChain.add(0, mInputFilterHost); + } + + nativeSetInputFilterEnabled(mPtr, !mInputFilterChain.isEmpty()); + } + } + + /** + * Registers a secondary input filter. These filters are always behind the "original" + * input filter. This ensures that all input events will be filtered by the + * {@code AccessibilityManagerService} first. + * <p> + * <b>Note:</b> Even though this implementation using AIDL interfaces, it is designed to only + * provide direct access. Therefore, any filter registering should reside in the + * system server DVM only! + * + * @param filter The input filter to register. + */ + public void registerSecondaryInputFilter(IInputFilter filter) { + synchronized (mInputFilterLock) { + ChainedInputFilterHost host = new ChainedInputFilterHost(filter, null); + if (!mInputFilterChain.isEmpty()) { + mInputFilterChain.get(mInputFilterChain.size() - 1).mNext = host; + } + host.connectLocked(); + mInputFilterChain.add(host); + + nativeSetInputFilterEnabled(mPtr, !mInputFilterChain.isEmpty()); + } + } + + public void unregisterSecondaryInputFilter(IInputFilter filter) { + synchronized (mInputFilterLock) { + int index = findInputFilterIndexLocked(filter); + if (index >= 0) { + ChainedInputFilterHost host = mInputFilterChain.get(index); + host.disconnectLocked(); + if (index >= 1) { + mInputFilterChain.get(index - 1).mNext = host.mNext; } + mInputFilterChain.remove(index); } - nativeSetInputFilterEnabled(mPtr, filter != null); + nativeSetInputFilterEnabled(mPtr, !mInputFilterChain.isEmpty()); + } + } + + private int findInputFilterIndexLocked(IInputFilter filter) { + for (int i = 0; i < mInputFilterChain.size(); i++) { + if (mInputFilterChain.get(i).mInputFilter == filter) { + return i; + } } + return -1; } @Override // Binder call @@ -1327,16 +1372,23 @@ public class InputManagerService extends IInputManager.Stub // Native callback. final boolean filterInputEvent(InputEvent event, int policyFlags) { + ChainedInputFilterHost head = null; synchronized (mInputFilterLock) { - if (mInputFilter != null) { - try { - mInputFilter.filterInputEvent(event, policyFlags); - } catch (RemoteException e) { - /* ignore */ - } - return false; + if (!mInputFilterChain.isEmpty()) { + head = mInputFilterChain.get(0); } } + // call filter input event outside of the lock. + // this is safe, because we know that mInputFilter never changes. + // we may loose a event, but this does not differ from the original implementation. + if (head != null) { + try { + head.mInputFilter.filterInputEvent(event, policyFlags); + } catch (RemoteException e) { + /* ignore */ + } + return false; + } event.recycle(); return true; } @@ -1561,10 +1613,32 @@ public class InputManagerService extends IInputManager.Stub /** * Hosting interface for input filters to call back into the input manager. */ - private final class InputFilterHost extends IInputFilterHost.Stub { + private final class ChainedInputFilterHost extends IInputFilterHost.Stub { + private final IInputFilter mInputFilter; + private ChainedInputFilterHost mNext; private boolean mDisconnected; + private ChainedInputFilterHost(IInputFilter filter, ChainedInputFilterHost next) { + mInputFilter = filter; + mNext = next; + mDisconnected = false; + } + + public void connectLocked() { + try { + mInputFilter.install(this); + } catch (RemoteException re) { + /* ignore */ + } + } + public void disconnectLocked() { + try { + mInputFilter.uninstall(); + } catch (RemoteException re) { + /* ignore */ + } + // DO NOT set mInputFilter to null here! mInputFilter is used outside of the lock! mDisconnected = true; } @@ -1576,9 +1650,17 @@ public class InputManagerService extends IInputManager.Stub synchronized (mInputFilterLock) { if (!mDisconnected) { - nativeInjectInputEvent(mPtr, event, 0, 0, - InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, - policyFlags | WindowManagerPolicy.FLAG_FILTERED); + if (mNext == null) { + nativeInjectInputEvent(mPtr, event, 0, 0, + InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, + policyFlags | WindowManagerPolicy.FLAG_FILTERED); + } else { + try { + mNext.mInputFilter.filterInputEvent(event, policyFlags); + } catch (RemoteException e) { + /* ignore */ + } + } } } } |
