diff --git a/services/core/java/com/android/server/policy/KeyCombinationManager.java b/services/core/java/com/android/server/policy/KeyCombinationManager.java index 9213c87f12eca..9dfaca8d163fc 100644 --- a/services/core/java/com/android/server/policy/KeyCombinationManager.java +++ b/services/core/java/com/android/server/policy/KeyCombinationManager.java @@ -106,16 +106,43 @@ public class KeyCombinationManager { return KeyEvent.keyCodeToString(mKeyCode1) + " + " + KeyEvent.keyCodeToString(mKeyCode2); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof TwoKeysCombinationRule) { + TwoKeysCombinationRule that = (TwoKeysCombinationRule) o; + return (mKeyCode1 == that.mKeyCode1 && mKeyCode2 == that.mKeyCode2) || ( + mKeyCode1 == that.mKeyCode2 && mKeyCode2 == that.mKeyCode1); + } + return false; + } + + @Override + public int hashCode() { + int result = mKeyCode1; + result = 31 * result + mKeyCode2; + return result; + } } - public KeyCombinationManager(Handler handler) { + KeyCombinationManager(Handler handler) { mHandler = handler; } void addRule(TwoKeysCombinationRule rule) { + if (mRules.contains(rule)) { + throw new IllegalArgumentException("Rule : " + rule + " already exists."); + } mRules.add(rule); } + void removeRule(TwoKeysCombinationRule rule) { + mRules.remove(rule); + } + /** * Check if the key event could be intercepted by combination key rule before it is dispatched * to a window. diff --git a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java index f00edf3a76c54..92f0011339a5f 100644 --- a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java +++ b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java @@ -151,6 +151,23 @@ public final class SingleKeyGestureDetector { + ", VeryLongPress=" + supportVeryLongPress() + ", MaxMultiPressCount=" + getMaxMultiPressCount(); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof SingleKeyRule) { + SingleKeyRule that = (SingleKeyRule) o; + return mKeyCode == that.mKeyCode; + } + return false; + } + + @Override + public int hashCode() { + return mKeyCode; + } } static SingleKeyGestureDetector get(Context context) { @@ -167,9 +184,16 @@ public final class SingleKeyGestureDetector { } void addRule(SingleKeyRule rule) { + if (mRules.contains(rule)) { + throw new IllegalArgumentException("Rule : " + rule + " already exists."); + } mRules.add(rule); } + void removeRule(SingleKeyRule rule) { + mRules.remove(rule); + } + void interceptKey(KeyEvent event, boolean interactive) { if (event.getAction() == KeyEvent.ACTION_DOWN) { // Store the non interactive state when first down. diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java index 4c698571db16e..487390d4411d9 100644 --- a/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java @@ -228,4 +228,30 @@ public class KeyCombinationManagerTests { mKeyCombinationManager.interceptKey(firstKeyDown, true); assertTrue(mKeyCombinationManager.getKeyInterceptTimeout(KEYCODE_VOLUME_UP) > eventTime); } -} + + @Test + public void testAddRemove() throws InterruptedException { + final KeyCombinationManager.TwoKeysCombinationRule rule = + new KeyCombinationManager.TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, + KEYCODE_POWER) { + @Override + void execute() { + mAction1Triggered.countDown(); + } + + @Override + void cancel() { + } + }; + + long eventTime = SystemClock.uptimeMillis(); + mKeyCombinationManager.removeRule(rule); + pressKeys(eventTime, KEYCODE_POWER, eventTime, KEYCODE_VOLUME_DOWN); + assertFalse(mAction1Triggered.await(SCHEDULE_TIME, TimeUnit.MILLISECONDS)); + + mKeyCombinationManager.addRule(rule); + eventTime = SystemClock.uptimeMillis(); + pressKeys(eventTime, KEYCODE_POWER, eventTime, KEYCODE_VOLUME_DOWN); + assertTrue(mAction1Triggered.await(SCHEDULE_TIME, TimeUnit.MILLISECONDS)); + } +} \ No newline at end of file diff --git a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java index 8f94468df126d..280afbadec30c 100644 --- a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java @@ -297,4 +297,23 @@ public class SingleKeyGestureTests { pressKey(KEYCODE_BACK, mLongPressTime); assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS)); } + + @Test + public void testAddRemove() throws InterruptedException { + final SingleKeyGestureDetector.SingleKeyRule rule = + new SingleKeyGestureDetector.SingleKeyRule(KEYCODE_POWER) { + @Override + void onPress(long downTime) { + mShortPressed.countDown(); + } + }; + + mDetector.removeRule(rule); + pressKey(KEYCODE_POWER, 0 /* pressTime */); + assertFalse(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS)); + + mDetector.addRule(rule); + pressKey(KEYCODE_POWER, 0 /* pressTime */); + assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS)); + } }