summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java63
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java323
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java20
-rw-r--r--tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt280
4 files changed, 455 insertions, 231 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ca6051874d78..74891205f3c6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3453,8 +3453,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// NOTE: Please try not to add new Shortcut combinations here and instead use KeyGestureEvents.
// Add shortcut trigger logic in {@code KeyGestureController} and add handling logic in
// {@link handleKeyGesture()}
- @SuppressLint("MissingPermission")
private boolean interceptSystemKeysAndShortcuts(IBinder focusedToken, KeyEvent event) {
+ if (useKeyGestureEventHandler()) {
+ return interceptSystemKeysAndShortcutsNew(focusedToken, event);
+ } else {
+ return interceptSystemKeysAndShortcutsOld(focusedToken, event);
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ private boolean interceptSystemKeysAndShortcutsOld(IBinder focusedToken, KeyEvent event) {
final boolean keyguardOn = keyguardOn();
final int keyCode = event.getKeyCode();
final int repeatCount = event.getRepeatCount();
@@ -3878,6 +3886,59 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return (metaState & KeyEvent.META_META_ON) != 0;
}
+ private boolean interceptSystemKeysAndShortcutsNew(IBinder focusedToken, KeyEvent event) {
+ final int keyCode = event.getKeyCode();
+ final int metaState = event.getMetaState();
+ final boolean keyguardOn = keyguardOn();
+
+ if (isUserSetupComplete() && !keyguardOn) {
+ if (mModifierShortcutManager.interceptKey(event)) {
+ dismissKeyboardShortcutsMenu();
+ return true;
+ }
+ }
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_HOME:
+ return handleHomeShortcuts(focusedToken, event);
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_MUTE:
+ if (mUseTvRouting || mHandleVolumeKeysInWM) {
+ // On TVs or when the configuration is enabled, volume keys never
+ // go to the foreground app.
+ dispatchDirectAudioEvent(event);
+ return true;
+ }
+
+ // If the device is in VR mode and keys are "internal" (e.g. on the side of the
+ // device), then drop the volume keys and don't forward it to the
+ // application/dispatch the audio event.
+ if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
+ final InputDevice d = event.getDevice();
+ if (d != null && !d.isExternal()) {
+ return true;
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_STEM_PRIMARY:
+ if (prepareToSendSystemKeyToApplication(focusedToken, event)) {
+ // Send to app.
+ return false;
+ } else {
+ // Intercepted.
+ sendSystemKeyToStatusBarAsync(event);
+ return true;
+ }
+ }
+ if (isValidGlobalKey(keyCode)
+ && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
+ return true;
+ }
+
+ // Reserve all the META modifier combos for system behavior
+ return (metaState & KeyEvent.META_META_ON) != 0;
+ }
+
@SuppressLint("MissingPermission")
private void initKeyGestures() {
if (!useKeyGestureEventHandler()) {
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
index 3d978e424375..81d63d31e776 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java
@@ -26,6 +26,7 @@ import static com.android.server.policy.PhoneWindowManager.SETTINGS_KEY_BEHAVIOR
import android.hardware.input.KeyGestureEvent;
import android.os.RemoteException;
+import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.view.KeyEvent;
@@ -56,7 +57,117 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
private static final int CTRL_ON = MODIFIER.get(KeyEvent.KEYCODE_CTRL_LEFT);
@Keep
- private static Object[][] shortcutTestArguments() {
+ private static Object[][] shortcutTestArgumentsNotMigratedToKeyGestureController() {
+ // testName, testKeys, expectedKeyGestureType, expectedKey, expectedModifierState
+ return new Object[][]{
+ {"HOME key -> Open Home", new int[]{KeyEvent.KEYCODE_HOME},
+ KeyGestureEvent.KEY_GESTURE_TYPE_HOME,
+ KeyEvent.KEYCODE_HOME, 0},
+ {"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK},
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK,
+ KeyEvent.KEYCODE_BACK, 0},
+ {"VOLUME_UP key -> Increase Volume", new int[]{KeyEvent.KEYCODE_VOLUME_UP},
+ KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_UP,
+ KeyEvent.KEYCODE_VOLUME_UP, 0},
+ {"VOLUME_DOWN key -> Decrease Volume", new int[]{KeyEvent.KEYCODE_VOLUME_DOWN},
+ KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_DOWN,
+ KeyEvent.KEYCODE_VOLUME_DOWN, 0},
+ {"VOLUME_MUTE key -> Mute Volume", new int[]{KeyEvent.KEYCODE_VOLUME_MUTE},
+ KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_MUTE,
+ KeyEvent.KEYCODE_VOLUME_MUTE, 0},
+ {"MUTE key -> Mute System Microphone", new int[]{KeyEvent.KEYCODE_MUTE},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE,
+ 0},
+ {"POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_POWER},
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER, KeyEvent.KEYCODE_POWER,
+ 0},
+ {"TV_POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_TV_POWER},
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER,
+ KeyEvent.KEYCODE_TV_POWER, 0},
+ {"SYSTEM_NAVIGATION_DOWN key -> System Navigation",
+ new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
+ 0},
+ {"SYSTEM_NAVIGATION_UP key -> System Navigation",
+ new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
+ 0},
+ {"SYSTEM_NAVIGATION_LEFT key -> System Navigation",
+ new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT,
+ 0},
+ {"SYSTEM_NAVIGATION_RIGHT key -> System Navigation",
+ new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
+ KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT, 0},
+ {"SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SLEEP},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SLEEP, 0},
+ {"SOFT_SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SOFT_SLEEP},
+ KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP,
+ 0},
+ {"WAKEUP key -> System Wakeup", new int[]{KeyEvent.KEYCODE_WAKEUP},
+ KeyGestureEvent.KEY_GESTURE_TYPE_WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0},
+ {"MEDIA_PLAY key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PLAY},
+ KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
+ KeyEvent.KEYCODE_MEDIA_PLAY, 0},
+ {"MEDIA_PAUSE key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PAUSE},
+ KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
+ KeyEvent.KEYCODE_MEDIA_PAUSE, 0},
+ {"MEDIA_PLAY_PAUSE key -> Media Control",
+ new int[]{KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE},
+ KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
+ KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0},
+ {"Meta + B -> Launch Default Browser", new int[]{META_KEY, KeyEvent.KEYCODE_B},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER,
+ KeyEvent.KEYCODE_B, META_ON},
+ {"EXPLORER key -> Launch Default Browser", new int[]{KeyEvent.KEYCODE_EXPLORER},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER,
+ KeyEvent.KEYCODE_EXPLORER, 0},
+ {"Meta + C -> Launch Default Contacts", new int[]{META_KEY, KeyEvent.KEYCODE_C},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS,
+ KeyEvent.KEYCODE_C, META_ON},
+ {"CONTACTS key -> Launch Default Contacts", new int[]{KeyEvent.KEYCODE_CONTACTS},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS,
+ KeyEvent.KEYCODE_CONTACTS, 0},
+ {"Meta + E -> Launch Default Email", new int[]{META_KEY, KeyEvent.KEYCODE_E},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL,
+ KeyEvent.KEYCODE_E, META_ON},
+ {"ENVELOPE key -> Launch Default Email", new int[]{KeyEvent.KEYCODE_ENVELOPE},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL,
+ KeyEvent.KEYCODE_ENVELOPE, 0},
+ {"Meta + K -> Launch Default Calendar", new int[]{META_KEY, KeyEvent.KEYCODE_K},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR,
+ KeyEvent.KEYCODE_K, META_ON},
+ {"CALENDAR key -> Launch Default Calendar", new int[]{KeyEvent.KEYCODE_CALENDAR},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR,
+ KeyEvent.KEYCODE_CALENDAR, 0},
+ {"Meta + P -> Launch Default Music", new int[]{META_KEY, KeyEvent.KEYCODE_P},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC,
+ KeyEvent.KEYCODE_P, META_ON},
+ {"MUSIC key -> Launch Default Music", new int[]{KeyEvent.KEYCODE_MUSIC},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC,
+ KeyEvent.KEYCODE_MUSIC, 0},
+ {"Meta + U -> Launch Default Calculator", new int[]{META_KEY, KeyEvent.KEYCODE_U},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR,
+ KeyEvent.KEYCODE_U, META_ON},
+ {"CALCULATOR key -> Launch Default Calculator",
+ new int[]{KeyEvent.KEYCODE_CALCULATOR},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR,
+ KeyEvent.KEYCODE_CALCULATOR, 0},
+ {"Meta + M -> Launch Default Maps", new int[]{META_KEY, KeyEvent.KEYCODE_M},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS,
+ KeyEvent.KEYCODE_M, META_ON},
+ {"Meta + S -> Launch Default Messaging App",
+ new int[]{META_KEY, KeyEvent.KEYCODE_S},
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING,
+ KeyEvent.KEYCODE_S, META_ON}};
+ }
+
+ @Keep
+ private static Object[][] shortcutTestArgumentsMigratedToKeyGestureController() {
// testName, testKeys, expectedKeyGestureType, expectedKey, expectedModifierState
return new Object[][]{
{"Meta + H -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_H},
@@ -64,9 +175,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
{"Meta + Enter -> Open Home", new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyEvent.KEYCODE_ENTER,
META_ON},
- {"HOME key -> Open Home", new int[]{KeyEvent.KEYCODE_HOME},
- KeyGestureEvent.KEY_GESTURE_TYPE_HOME,
- KeyEvent.KEYCODE_HOME, 0},
{"RECENT_APPS key -> Open Overview", new int[]{KeyEvent.KEYCODE_RECENT_APPS},
KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS,
KeyEvent.KEYCODE_RECENT_APPS, 0},
@@ -76,9 +184,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
{"Alt + Tab -> Open Overview", new int[]{ALT_KEY, KeyEvent.KEYCODE_TAB},
KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS, KeyEvent.KEYCODE_TAB,
ALT_ON},
- {"BACK key -> Go back", new int[]{KeyEvent.KEYCODE_BACK},
- KeyGestureEvent.KEY_GESTURE_TYPE_BACK,
- KeyEvent.KEYCODE_BACK, 0},
{"Meta + Escape -> Go back", new int[]{META_KEY, KeyEvent.KEYCODE_ESCAPE},
KeyGestureEvent.KEY_GESTURE_TYPE_BACK, KeyEvent.KEYCODE_ESCAPE,
META_ON},
@@ -138,15 +243,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
new int[]{KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE},
KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE,
KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE, 0},
- {"VOLUME_UP key -> Increase Volume", new int[]{KeyEvent.KEYCODE_VOLUME_UP},
- KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_UP,
- KeyEvent.KEYCODE_VOLUME_UP, 0},
- {"VOLUME_DOWN key -> Decrease Volume", new int[]{KeyEvent.KEYCODE_VOLUME_DOWN},
- KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_DOWN,
- KeyEvent.KEYCODE_VOLUME_DOWN, 0},
- {"VOLUME_MUTE key -> Mute Volume", new int[]{KeyEvent.KEYCODE_VOLUME_MUTE},
- KeyGestureEvent.KEY_GESTURE_TYPE_VOLUME_MUTE,
- KeyEvent.KEYCODE_VOLUME_MUTE, 0},
{"ALL_APPS key -> Open App Drawer",
new int[]{KeyEvent.KEYCODE_ALL_APPS},
KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS,
@@ -170,9 +266,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
{"CAPS_LOCK key -> Toggle CapsLock", new int[]{KeyEvent.KEYCODE_CAPS_LOCK},
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK,
KeyEvent.KEYCODE_CAPS_LOCK, 0},
- {"MUTE key -> Mute System Microphone", new int[]{KeyEvent.KEYCODE_MUTE},
- KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_MUTE, KeyEvent.KEYCODE_MUTE,
- 0},
{"Meta + Ctrl + DPAD_UP -> Split screen navigation",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_UP},
KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION,
@@ -194,92 +287,6 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
{"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N},
KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_NOTES, KeyEvent.KEYCODE_N,
META_ON | CTRL_ON},
- {"POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_POWER},
- KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER, KeyEvent.KEYCODE_POWER,
- 0},
- {"TV_POWER key -> Toggle Power", new int[]{KeyEvent.KEYCODE_TV_POWER},
- KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_POWER,
- KeyEvent.KEYCODE_TV_POWER, 0},
- {"SYSTEM_NAVIGATION_DOWN key -> System Navigation",
- new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN},
- KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
- KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
- 0},
- {"SYSTEM_NAVIGATION_UP key -> System Navigation",
- new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP},
- KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
- KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
- 0},
- {"SYSTEM_NAVIGATION_LEFT key -> System Navigation",
- new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT},
- KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
- KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT,
- 0},
- {"SYSTEM_NAVIGATION_RIGHT key -> System Navigation",
- new int[]{KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT},
- KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_NAVIGATION,
- KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT, 0},
- {"SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SLEEP},
- KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SLEEP, 0},
- {"SOFT_SLEEP key -> System Sleep", new int[]{KeyEvent.KEYCODE_SOFT_SLEEP},
- KeyGestureEvent.KEY_GESTURE_TYPE_SLEEP, KeyEvent.KEYCODE_SOFT_SLEEP,
- 0},
- {"WAKEUP key -> System Wakeup", new int[]{KeyEvent.KEYCODE_WAKEUP},
- KeyGestureEvent.KEY_GESTURE_TYPE_WAKEUP, KeyEvent.KEYCODE_WAKEUP, 0},
- {"MEDIA_PLAY key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PLAY},
- KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
- KeyEvent.KEYCODE_MEDIA_PLAY, 0},
- {"MEDIA_PAUSE key -> Media Control", new int[]{KeyEvent.KEYCODE_MEDIA_PAUSE},
- KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
- KeyEvent.KEYCODE_MEDIA_PAUSE, 0},
- {"MEDIA_PLAY_PAUSE key -> Media Control",
- new int[]{KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE},
- KeyGestureEvent.KEY_GESTURE_TYPE_MEDIA_KEY,
- KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0},
- {"Meta + B -> Launch Default Browser", new int[]{META_KEY, KeyEvent.KEYCODE_B},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER,
- KeyEvent.KEYCODE_B, META_ON},
- {"EXPLORER key -> Launch Default Browser", new int[]{KeyEvent.KEYCODE_EXPLORER},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_BROWSER,
- KeyEvent.KEYCODE_EXPLORER, 0},
- {"Meta + C -> Launch Default Contacts", new int[]{META_KEY, KeyEvent.KEYCODE_C},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS,
- KeyEvent.KEYCODE_C, META_ON},
- {"CONTACTS key -> Launch Default Contacts", new int[]{KeyEvent.KEYCODE_CONTACTS},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CONTACTS,
- KeyEvent.KEYCODE_CONTACTS, 0},
- {"Meta + E -> Launch Default Email", new int[]{META_KEY, KeyEvent.KEYCODE_E},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL,
- KeyEvent.KEYCODE_E, META_ON},
- {"ENVELOPE key -> Launch Default Email", new int[]{KeyEvent.KEYCODE_ENVELOPE},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_EMAIL,
- KeyEvent.KEYCODE_ENVELOPE, 0},
- {"Meta + K -> Launch Default Calendar", new int[]{META_KEY, KeyEvent.KEYCODE_K},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR,
- KeyEvent.KEYCODE_K, META_ON},
- {"CALENDAR key -> Launch Default Calendar", new int[]{KeyEvent.KEYCODE_CALENDAR},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALENDAR,
- KeyEvent.KEYCODE_CALENDAR, 0},
- {"Meta + P -> Launch Default Music", new int[]{META_KEY, KeyEvent.KEYCODE_P},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC,
- KeyEvent.KEYCODE_P, META_ON},
- {"MUSIC key -> Launch Default Music", new int[]{KeyEvent.KEYCODE_MUSIC},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MUSIC,
- KeyEvent.KEYCODE_MUSIC, 0},
- {"Meta + U -> Launch Default Calculator", new int[]{META_KEY, KeyEvent.KEYCODE_U},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR,
- KeyEvent.KEYCODE_U, META_ON},
- {"CALCULATOR key -> Launch Default Calculator",
- new int[]{KeyEvent.KEYCODE_CALCULATOR},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_CALCULATOR,
- KeyEvent.KEYCODE_CALCULATOR, 0},
- {"Meta + M -> Launch Default Maps", new int[]{META_KEY, KeyEvent.KEYCODE_M},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MAPS,
- KeyEvent.KEYCODE_M, META_ON},
- {"Meta + S -> Launch Default Messaging App",
- new int[]{META_KEY, KeyEvent.KEYCODE_S},
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_DEFAULT_MESSAGING,
- KeyEvent.KEYCODE_S, META_ON},
{"Meta + Ctrl + DPAD_DOWN -> Enter desktop mode",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_DOWN},
KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE,
@@ -296,72 +303,14 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_NOTIFICATION_PANEL,
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
KeyEvent.KEYCODE_HOME, 0},
- {"Long press META + ENTER -> Toggle Notification panel",
- new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
- LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
- KeyEvent.KEYCODE_ENTER,
- META_ON},
- {"Long press META + H -> Toggle Notification panel",
- new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_NOTIFICATION_PANEL,
- KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
- KeyEvent.KEYCODE_H, META_ON},
{"Long press HOME key -> Launch assistant",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ASSIST,
KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT,
KeyEvent.KEYCODE_HOME, 0},
- {"Long press META + ENTER -> Launch assistant",
- new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ASSIST,
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT,
- KeyEvent.KEYCODE_ENTER, META_ON},
- {"Long press META + H -> Launch assistant",
- new int[]{META_KEY, KeyEvent.KEYCODE_H}, LONG_PRESS_HOME_ASSIST,
- KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT, KeyEvent.KEYCODE_H,
- META_ON},
{"Long press HOME key -> Open App Drawer",
new int[]{KeyEvent.KEYCODE_HOME}, LONG_PRESS_HOME_ALL_APPS,
KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS,
- KeyEvent.KEYCODE_HOME, 0},
- {"Long press META + ENTER -> Open App Drawer",
- new int[]{META_KEY, KeyEvent.KEYCODE_ENTER}, LONG_PRESS_HOME_ALL_APPS,
- KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS,
- KeyEvent.KEYCODE_ENTER, META_ON},
- {"Long press META + H -> Open App Drawer",
- new int[]{META_KEY, KeyEvent.KEYCODE_H},
- LONG_PRESS_HOME_ALL_APPS,
- KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS,
- KeyEvent.KEYCODE_H, META_ON}};
- }
-
- @Keep
- private static Object[][] doubleTapOnHomeTestArguments() {
- // testName, testKeys, doubleTapOnHomeBehavior, expectedKeyGestureType, expectedKey,
- // expectedModifierState
- return new Object[][]{
- {"Double tap HOME -> Open App switcher",
- new int[]{KeyEvent.KEYCODE_HOME}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_HOME,
- 0},
- {"Double tap META + ENTER -> Open App switcher",
- new int[]{META_KEY, KeyEvent.KEYCODE_ENTER},
- DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH,
- KeyEvent.KEYCODE_ENTER, META_ON},
- {"Double tap META + H -> Open App switcher",
- new int[]{META_KEY, KeyEvent.KEYCODE_H}, DOUBLE_TAP_HOME_RECENT_SYSTEM_UI,
- KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH, KeyEvent.KEYCODE_H,
- META_ON}};
- }
-
- @Keep
- private static Object[][] settingsKeyTestArguments() {
- // testName, testKeys, settingsKeyBehavior, expectedKeyGestureType, expectedKey,
- // expectedModifierState
- return new Object[][]{
- {"SETTINGS key -> Toggle Notification panel", new int[]{KeyEvent.KEYCODE_SETTINGS},
- SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL,
- KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
- KeyEvent.KEYCODE_SETTINGS, 0}};
+ KeyEvent.KEYCODE_HOME, 0}};
}
@Before
@@ -381,8 +330,18 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
}
@Test
- @Parameters(method = "shortcutTestArguments")
- public void testShortcut(String testName, int[] testKeys,
+ @Parameters(method = "shortcutTestArgumentsNotMigratedToKeyGestureController")
+ public void testShortcuts_notMigratedToKeyGestureController(String testName,
+ int[] testKeys, @KeyGestureEvent.KeyGestureType int expectedKeyGestureType,
+ int expectedKey, int expectedModifierState) {
+ testShortcutInternal(testName, testKeys, expectedKeyGestureType, expectedKey,
+ expectedModifierState);
+ }
+
+ @Test
+ @Parameters(method = "shortcutTestArgumentsMigratedToKeyGestureController")
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
+ public void testShortcuts_migratedToKeyGestureController(String testName, int[] testKeys,
@KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
int expectedModifierState) {
testShortcutInternal(testName, testKeys, expectedKeyGestureType, expectedKey,
@@ -402,31 +361,29 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase {
}
@Test
- @Parameters(method = "doubleTapOnHomeTestArguments")
- public void testDoubleTapOnHomeBehavior(String testName, int[] testKeys,
- int doubleTapOnHomeBehavior,
- @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
- int expectedModifierState) {
- mPhoneWindowManager.overriderDoubleTapOnHomeBehavior(doubleTapOnHomeBehavior);
- sendKeyCombination(testKeys, 0 /* duration */);
- sendKeyCombination(testKeys, 0 /* duration */);
+ public void testDoubleTapOnHomeBehavior_AppSwitchBehavior() {
+ mPhoneWindowManager.overriderDoubleTapOnHomeBehavior(DOUBLE_TAP_HOME_RECENT_SYSTEM_UI);
+ sendKeyCombination(new int[]{KeyEvent.KEYCODE_HOME}, 0 /* duration */);
+ sendKeyCombination(new int[]{KeyEvent.KEYCODE_HOME}, 0 /* duration */);
mPhoneWindowManager.assertKeyGestureCompleted(
- new int[]{expectedKey}, expectedModifierState, expectedKeyGestureType,
- "Failed while executing " + testName);
+ new int[]{KeyEvent.KEYCODE_HOME}, /* modifierState = */0,
+ KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH,
+ "Failed while executing Double tap HOME -> Open App switcher");
}
@Test
- @Parameters(method = "settingsKeyTestArguments")
- public void testSettingsKey(String testName, int[] testKeys, int settingsKeyBehavior,
- @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey,
- int expectedModifierState) {
- mPhoneWindowManager.overrideSettingsKeyBehavior(settingsKeyBehavior);
- testShortcutInternal(testName, testKeys, expectedKeyGestureType, expectedKey,
- expectedModifierState);
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
+ public void testSettingsKey_ToggleNotificationBehavior() {
+ mPhoneWindowManager.overrideSettingsKeyBehavior(SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL);
+ testShortcutInternal("SETTINGS key -> Toggle Notification panel",
+ new int[]{KeyEvent.KEYCODE_SETTINGS},
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
+ KeyEvent.KEYCODE_SETTINGS, 0);
}
@Test
@EnableFlags(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testBugreportShortcutPress() {
testShortcutInternal("Meta + Ctrl + Del -> Trigger bug report",
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DEL},
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 43171f847818..b54e74fb5188 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -119,6 +119,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* ALT + TAB to show recent apps.
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testAltTab() {
mPhoneWindowManager.overrideStatusBarManagerInternal();
sendKeyCombination(new int[]{KEYCODE_ALT_LEFT, KEYCODE_TAB}, 0);
@@ -158,6 +159,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* META + CTRL+ S to take screenshot.
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testMetaCtrlS() {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_S}, 0);
mPhoneWindowManager.assertTakeScreenshotCalled();
@@ -167,6 +169,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* META + N to expand notification panel.
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testMetaN() throws RemoteException {
mPhoneWindowManager.overrideTogglePanel();
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_N}, 0);
@@ -177,6 +180,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* META + SLASH to toggle shortcuts menu.
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testMetaSlash() {
mPhoneWindowManager.overrideStatusBarManagerInternal();
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SLASH}, 0);
@@ -187,6 +191,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* META + ALT to toggle Cap Lock.
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testMetaAlt() {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ALT_LEFT}, 0);
mPhoneWindowManager.assertToggleCapsLock();
@@ -196,6 +201,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* META + H to go to homescreen
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testMetaH() {
mPhoneWindowManager.overrideLaunchHome();
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_H}, 0);
@@ -206,6 +212,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* META + ENTER to go to homescreen
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testMetaEnter() {
mPhoneWindowManager.overrideLaunchHome();
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ENTER}, 0);
@@ -216,6 +223,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* Sends a KEYCODE_BRIGHTNESS_DOWN event and validates the brightness is decreased as expected;
*/
@Test
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testKeyCodeBrightnessDown() {
float[] currentBrightness = new float[]{0.1f, 0.05f, 0.0f};
float[] newBrightness = new float[]{0.065738f, 0.0275134f, 0.0f};
@@ -231,9 +239,9 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* Sends a KEYCODE_SCREENSHOT and validates screenshot is taken if flag is enabled
*/
@Test
+ @EnableFlags(com.android.hardware.input.Flags.FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE)
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testTakeScreenshot_flagEnabled() {
- mSetFlagsRule.enableFlags(com.android.hardware.input.Flags
- .FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE);
sendKeyCombination(new int[]{KEYCODE_SCREENSHOT}, 0);
mPhoneWindowManager.assertTakeScreenshotCalled();
}
@@ -242,9 +250,9 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* Sends a KEYCODE_SCREENSHOT and validates screenshot is not taken if flag is disabled
*/
@Test
+ @DisableFlags({com.android.hardware.input.Flags.FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE,
+ com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER})
public void testTakeScreenshot_flagDisabled() {
- mSetFlagsRule.disableFlags(com.android.hardware.input.Flags
- .FLAG_EMOJI_AND_SCREENSHOT_KEYCODES_AVAILABLE);
sendKeyCombination(new int[]{KEYCODE_SCREENSHOT}, 0);
mPhoneWindowManager.assertTakeScreenshotNotCalled();
}
@@ -254,6 +262,7 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
*/
@Test
@EnableFlags(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER)
public void testTakeBugReport_flagEnabled() throws RemoteException {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
mPhoneWindowManager.assertTakeBugreport(true);
@@ -263,7 +272,8 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
* META+CTRL+BACKSPACE for taking a bugreport does nothing when the flag is disabledd.
*/
@Test
- @DisableFlags(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ @DisableFlags({com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT,
+ com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER})
public void testTakeBugReport_flagDisabled() throws RemoteException {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
mPhoneWindowManager.assertTakeBugreport(false);
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index ba360070abc3..b448c7eb3092 100644
--- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -18,6 +18,7 @@ package com.android.server.input
import android.content.Context
import android.content.ContextWrapper
+import android.content.res.Resources
import android.hardware.input.IInputManager
import android.hardware.input.AidlKeyGestureEvent
import android.hardware.input.IKeyGestureEventListener
@@ -25,15 +26,18 @@ import android.hardware.input.IKeyGestureHandler
import android.hardware.input.InputManager
import android.hardware.input.InputManagerGlobal
import android.hardware.input.KeyGestureEvent
-import android.hardware.input.KeyGestureEvent.KeyGestureType
import android.os.IBinder
import android.os.Process
+import android.os.SystemProperties
import android.os.test.TestLooper
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.Presubmit
+import android.platform.test.flag.junit.SetFlagsRule
import android.view.InputDevice
-import android.view.KeyCharacterMap
import android.view.KeyEvent
import androidx.test.core.app.ApplicationProvider
+import com.android.internal.R
import com.android.internal.annotations.Keep
import com.android.internal.util.FrameworkStatsLog
import com.android.modules.utils.testing.ExtendedMockitoRule
@@ -78,32 +82,43 @@ class KeyGestureControllerTests {
KeyEvent.KEYCODE_META_LEFT to (KeyEvent.META_META_LEFT_ON or KeyEvent.META_META_ON),
KeyEvent.KEYCODE_META_RIGHT to (KeyEvent.META_META_RIGHT_ON or KeyEvent.META_META_ON),
)
+ const val SEARCH_KEY_BEHAVIOR_DEFAULT_SEARCH = 0
+ const val SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY = 1
+ const val SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY = 0
+ const val SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL = 1
+ const val SETTINGS_KEY_BEHAVIOR_NOTHING = 2
}
@JvmField
@Rule
val extendedMockitoRule = ExtendedMockitoRule.Builder(this)
- .mockStatic(FrameworkStatsLog::class.java).build()!!
+ .mockStatic(FrameworkStatsLog::class.java)
+ .mockStatic(SystemProperties::class.java).build()!!
+
+ @JvmField
+ @Rule
+ val rule = SetFlagsRule()
@Mock
private lateinit var iInputManager: IInputManager
+ @Mock
+ private lateinit var resources: Resources
+
private var currentPid = 0
- private lateinit var keyGestureController: KeyGestureController
private lateinit var context: Context
private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
private lateinit var testLooper: TestLooper
private var events = mutableListOf<KeyGestureEvent>()
- private var handleEvents = mutableListOf<KeyGestureEvent>()
@Before
fun setup() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+ Mockito.`when`(context.resources).thenReturn(resources)
inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManager)
setupInputDevices()
testLooper = TestLooper()
currentPid = Process.myPid()
- keyGestureController = KeyGestureController(context, testLooper.looper)
}
private fun setupInputDevices() {
@@ -116,7 +131,7 @@ class KeyGestureControllerTests {
Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardDevice)
}
- private fun notifyHomeGestureCompleted() {
+ private fun notifyHomeGestureCompleted(keyGestureController: KeyGestureController) {
keyGestureController.notifyKeyGestureCompleted(DEVICE_ID, intArrayOf(KeyEvent.KEYCODE_H),
KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON,
KeyGestureEvent.KEY_GESTURE_TYPE_HOME)
@@ -124,11 +139,12 @@ class KeyGestureControllerTests {
@Test
fun testKeyGestureEvent_registerUnregisterListener() {
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
val listener = KeyGestureEventListener()
// Register key gesture event listener
keyGestureController.registerKeyGestureEventListener(listener, 0)
- notifyHomeGestureCompleted()
+ notifyHomeGestureCompleted(keyGestureController)
testLooper.dispatchAll()
assertEquals(
"Listener should get callbacks on key gesture event completed",
@@ -144,7 +160,7 @@ class KeyGestureControllerTests {
// Unregister listener
events.clear()
keyGestureController.unregisterKeyGestureEventListener(listener, 0)
- notifyHomeGestureCompleted()
+ notifyHomeGestureCompleted(keyGestureController)
testLooper.dispatchAll()
assertEquals(
"Listener should not get callback after being unregistered",
@@ -155,6 +171,8 @@ class KeyGestureControllerTests {
@Test
fun testKeyGestureEvent_multipleGestureHandlers() {
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+
// Set up two callbacks.
var callbackCount1 = 0
var callbackCount2 = 0
@@ -406,6 +424,14 @@ class KeyGestureControllerTests {
intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
),
TestData(
+ "META + / -> Open Shortcut Helper",
+ intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_SLASH),
+ KeyGestureEvent.KEY_GESTURE_TYPE_OPEN_SHORTCUT_HELPER,
+ intArrayOf(KeyEvent.KEYCODE_SLASH),
+ KeyEvent.META_META_ON,
+ intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+ ),
+ TestData(
"BRIGHTNESS_UP -> Brightness Up",
intArrayOf(KeyEvent.KEYCODE_BRIGHTNESS_UP),
KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_UP,
@@ -534,6 +560,188 @@ class KeyGestureControllerTests {
@Test
@Parameters(method = "keyGestureEventHandlerTestArguments")
fun testKeyGestures(test: TestData) {
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureInternal(keyGestureController, test)
+ }
+
+ @Test
+ fun testKeycodesFullyConsumed_irrespectiveOfHandlers() {
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ val testKeys = intArrayOf(
+ KeyEvent.KEYCODE_RECENT_APPS,
+ KeyEvent.KEYCODE_APP_SWITCH,
+ KeyEvent.KEYCODE_BRIGHTNESS_UP,
+ KeyEvent.KEYCODE_BRIGHTNESS_DOWN,
+ KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN,
+ KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP,
+ KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE,
+ KeyEvent.KEYCODE_ALL_APPS,
+ KeyEvent.KEYCODE_NOTIFICATION,
+ KeyEvent.KEYCODE_SETTINGS,
+ KeyEvent.KEYCODE_LANGUAGE_SWITCH,
+ KeyEvent.KEYCODE_SCREENSHOT,
+ KeyEvent.KEYCODE_META_LEFT,
+ KeyEvent.KEYCODE_META_RIGHT,
+ KeyEvent.KEYCODE_ASSIST,
+ KeyEvent.KEYCODE_VOICE_ASSIST,
+ KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY,
+ KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY,
+ KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY,
+ KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL,
+ )
+
+ val handler = KeyGestureHandler { _, _ -> false }
+ keyGestureController.registerKeyGestureHandler(handler, 0)
+
+ for (key in testKeys) {
+ sendKeys(keyGestureController, intArrayOf(key), assertAllConsumed = true)
+ }
+ }
+
+ @Test
+ fun testSearchKeyGestures_defaultSearch() {
+ Mockito.`when`(resources.getInteger(R.integer.config_searchKeyBehavior))
+ .thenReturn(SEARCH_KEY_BEHAVIOR_DEFAULT_SEARCH)
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureNotProduced(
+ keyGestureController,
+ "SEARCH -> Default Search",
+ intArrayOf(KeyEvent.KEYCODE_SEARCH),
+ )
+ }
+
+ @Test
+ fun testSearchKeyGestures_searchActivity() {
+ Mockito.`when`(resources.getInteger(R.integer.config_searchKeyBehavior))
+ .thenReturn(SEARCH_KEY_BEHAVIOR_TARGET_ACTIVITY)
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureInternal(
+ keyGestureController,
+ TestData(
+ "SEARCH -> Launch Search Activity",
+ intArrayOf(KeyEvent.KEYCODE_SEARCH),
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SEARCH,
+ intArrayOf(KeyEvent.KEYCODE_SEARCH),
+ 0,
+ intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+ )
+ )
+ }
+
+ @Test
+ fun testSettingKeyGestures_doNothing() {
+ Mockito.`when`(resources.getInteger(R.integer.config_settingsKeyBehavior))
+ .thenReturn(SETTINGS_KEY_BEHAVIOR_NOTHING)
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureNotProduced(
+ keyGestureController,
+ "SETTINGS -> Do Nothing",
+ intArrayOf(KeyEvent.KEYCODE_SETTINGS),
+ )
+ }
+
+ @Test
+ fun testSettingKeyGestures_settingsActivity() {
+ Mockito.`when`(resources.getInteger(R.integer.config_settingsKeyBehavior))
+ .thenReturn(SETTINGS_KEY_BEHAVIOR_SETTINGS_ACTIVITY)
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureInternal(
+ keyGestureController,
+ TestData(
+ "SETTINGS -> Launch Settings Activity",
+ intArrayOf(KeyEvent.KEYCODE_SETTINGS),
+ KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS,
+ intArrayOf(KeyEvent.KEYCODE_SETTINGS),
+ 0,
+ intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+ )
+ )
+ }
+
+ @Test
+ fun testSettingKeyGestures_notificationPanel() {
+ Mockito.`when`(resources.getInteger(R.integer.config_settingsKeyBehavior))
+ .thenReturn(SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL)
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureInternal(
+ keyGestureController,
+ TestData(
+ "SETTINGS -> Toggle Notification Panel",
+ intArrayOf(KeyEvent.KEYCODE_SETTINGS),
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
+ intArrayOf(KeyEvent.KEYCODE_SETTINGS),
+ 0,
+ intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+ )
+ )
+ }
+
+ @Test
+ @EnableFlags(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ fun testTriggerBugReport() {
+ Mockito.`when`(SystemProperties.get("ro.debuggable")).thenReturn("1")
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureInternal(
+ keyGestureController,
+ TestData(
+ "META + CTRL + DEL -> Trigger Bug Report",
+ intArrayOf(
+ KeyEvent.KEYCODE_META_LEFT,
+ KeyEvent.KEYCODE_CTRL_LEFT,
+ KeyEvent.KEYCODE_DEL
+ ),
+ KeyGestureEvent.KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT,
+ intArrayOf(KeyEvent.KEYCODE_DEL),
+ KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+ intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+ )
+ )
+ }
+
+ @Test
+ @DisableFlags(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ fun testTriggerBugReport_flagDisabled() {
+ Mockito.`when`(SystemProperties.get("ro.debuggable")).thenReturn("1")
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureInternal(
+ keyGestureController,
+ TestData(
+ "META + CTRL + DEL -> Not Trigger Bug Report (Fallback to BACK)",
+ intArrayOf(
+ KeyEvent.KEYCODE_META_LEFT,
+ KeyEvent.KEYCODE_CTRL_LEFT,
+ KeyEvent.KEYCODE_DEL
+ ),
+ KeyGestureEvent.KEY_GESTURE_TYPE_BACK,
+ intArrayOf(KeyEvent.KEYCODE_DEL),
+ KeyEvent.META_META_ON,
+ intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+ )
+ )
+ }
+
+ @Test
+ fun testCapsLockPressNotified() {
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ val listener = KeyGestureEventListener()
+
+ keyGestureController.registerKeyGestureEventListener(listener, 0)
+ sendKeys(keyGestureController, intArrayOf(KeyEvent.KEYCODE_CAPS_LOCK))
+ testLooper.dispatchAll()
+ assertEquals(
+ "Listener should get callbacks on key gesture event completed",
+ 1,
+ events.size
+ )
+ assertEquals(
+ "Listener should get callback for Toggle Caps Lock key gesture complete event",
+ KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK,
+ events[0].keyGestureType
+ )
+ }
+
+ private fun testKeyGestureInternal(keyGestureController: KeyGestureController, test: TestData) {
+ var handleEvents = mutableListOf<KeyGestureEvent>()
val handler = KeyGestureHandler { event, _ ->
handleEvents.add(KeyGestureEvent(event))
true
@@ -541,7 +749,7 @@ class KeyGestureControllerTests {
keyGestureController.registerKeyGestureHandler(handler, 0)
handleEvents.clear()
- sendKeys(test.keys, /* assertAllConsumed = */ false)
+ sendKeys(keyGestureController, test.keys)
assertEquals(
"Test: $test doesn't produce correct number of key gesture events",
@@ -575,45 +783,33 @@ class KeyGestureControllerTests {
keyGestureController.unregisterKeyGestureHandler(handler, 0)
}
- @Test
- fun testKeycodesFullyConsumed_irrespectiveOfHandlers() {
- val testKeys = intArrayOf(
- KeyEvent.KEYCODE_RECENT_APPS,
- KeyEvent.KEYCODE_APP_SWITCH,
- KeyEvent.KEYCODE_BRIGHTNESS_UP,
- KeyEvent.KEYCODE_BRIGHTNESS_DOWN,
- KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN,
- KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP,
- KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE,
- KeyEvent.KEYCODE_ALL_APPS,
- KeyEvent.KEYCODE_NOTIFICATION,
- KeyEvent.KEYCODE_SETTINGS,
- KeyEvent.KEYCODE_LANGUAGE_SWITCH,
- KeyEvent.KEYCODE_SCREENSHOT,
- KeyEvent.KEYCODE_META_LEFT,
- KeyEvent.KEYCODE_META_RIGHT,
- KeyEvent.KEYCODE_ASSIST,
- KeyEvent.KEYCODE_VOICE_ASSIST,
- KeyEvent.KEYCODE_STYLUS_BUTTON_PRIMARY,
- KeyEvent.KEYCODE_STYLUS_BUTTON_SECONDARY,
- KeyEvent.KEYCODE_STYLUS_BUTTON_TERTIARY,
- KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL,
- )
-
- val handler = KeyGestureHandler { _, _ -> false }
+ private fun testKeyGestureNotProduced(
+ keyGestureController: KeyGestureController,
+ testName: String,
+ testKeys: IntArray
+ ) {
+ var handleEvents = mutableListOf<KeyGestureEvent>()
+ val handler = KeyGestureHandler { event, _ ->
+ handleEvents.add(KeyGestureEvent(event))
+ true
+ }
keyGestureController.registerKeyGestureHandler(handler, 0)
+ handleEvents.clear()
- for (key in testKeys) {
- sendKeys(intArrayOf(key), /* assertAllConsumed = */ true)
- }
+ sendKeys(keyGestureController, testKeys)
+ assertEquals("Test: $testName should not produce Key gesture", 0, handleEvents.size)
}
- private fun sendKeys(testKeys: IntArray, assertAllConsumed: Boolean) {
+ private fun sendKeys(
+ keyGestureController: KeyGestureController,
+ testKeys: IntArray,
+ assertAllConsumed: Boolean = false
+ ) {
var metaState = 0
for (key in testKeys) {
val downEvent = KeyEvent(
/* downTime = */0, /* eventTime = */ 0, KeyEvent.ACTION_DOWN, key,
- 0 /*repeat*/, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
+ 0 /*repeat*/, metaState, DEVICE_ID, 0 /*scancode*/,
0 /*flags*/, InputDevice.SOURCE_KEYBOARD
)
val consumed =
@@ -633,7 +829,7 @@ class KeyGestureControllerTests {
for (key in testKeys.reversed()) {
val upEvent = KeyEvent(
/* downTime = */0, /* eventTime = */ 0, KeyEvent.ACTION_UP, key,
- 0 /*repeat*/, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
+ 0 /*repeat*/, metaState, DEVICE_ID, 0 /*scancode*/,
0 /*flags*/, InputDevice.SOURCE_KEYBOARD
)
val consumed =