Loading core/java/android/hardware/input/InputSettings.java +14 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,20 @@ public class InputSettings { @SuppressLint("UnflaggedApi") // TestApi without associated feature. public static final int DEFAULT_POINTER_SPEED = 0; /** * Bounce Keys Threshold: The default value of the threshold (500 ms). * * @hide */ public static final int DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS = 500; /** * Slow Keys Threshold: The default value of the threshold (500 ms). * * @hide */ public static final int DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS = 500; /** * The maximum allowed obscuring opacity by UID to propagate touches (0 <= x <= 1). * @hide Loading core/java/android/hardware/input/KeyGestureEvent.java +16 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,10 @@ public final class KeyGestureEvent { public static final int KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS = 61; public static final int KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY = 62; public static final int KEY_GESTURE_TYPE_TOGGLE_TALKBACK = 63; public static final int KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS = 64; public static final int KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS = 65; public static final int KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS = 66; public static final int KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS = 67; public static final int FLAG_CANCELLED = 1; Loading Loading @@ -187,6 +191,10 @@ public final class KeyGestureEvent { KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS, KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY, KEY_GESTURE_TYPE_TOGGLE_TALKBACK, KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS, KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS, KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS, KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -733,6 +741,14 @@ public final class KeyGestureEvent { return "KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS"; case KEY_GESTURE_TYPE_TOGGLE_TALKBACK: return "KEY_GESTURE_TYPE_TOGGLE_TALKBACK"; case KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS"; case KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS"; case KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS"; case KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS"; default: return Integer.toHexString(value); } Loading services/core/java/com/android/server/input/KeyGestureController.java +49 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.hardware.input.AidlKeyGestureEvent; import android.hardware.input.IKeyGestureEventListener; import android.hardware.input.IKeyGestureHandler; import android.hardware.input.InputManager; import android.hardware.input.InputSettings; import android.hardware.input.KeyGestureEvent; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -589,6 +590,54 @@ final class KeyGestureController { } } break; case KeyEvent.KEYCODE_3: if (InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_4: if (InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_5: if (InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_6: if (InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_DEL: if (newBugreportKeyboardShortcut()) { if (firstDown && mEnableBugReportKeyboardShortcut && event.isMetaPressed() Loading services/core/java/com/android/server/policy/PhoneWindowManager.java +126 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; import android.hardware.input.AppLaunchData; import android.hardware.input.InputManager; import android.hardware.input.InputSettings; import android.hardware.input.KeyGestureEvent; import android.media.AudioManager; import android.media.AudioManagerInternal; Loading Loading @@ -3617,6 +3618,68 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } break; case KeyEvent.KEYCODE_3: if (InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean bounceKeysEnabled = InputSettings.isAccessibilityBounceKeysEnabled( mContext); InputSettings.setAccessibilityBounceKeysThreshold(mContext, bounceKeysEnabled ? 0 : InputSettings.DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS); return true; } } break; case KeyEvent.KEYCODE_4: if (InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean mouseKeysEnabled = InputSettings.isAccessibilityMouseKeysEnabled( mContext); InputSettings.setAccessibilityMouseKeysEnabled(mContext, !mouseKeysEnabled); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS); return true; } } break; case KeyEvent.KEYCODE_5: if (InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean stickyKeysEnabled = InputSettings.isAccessibilityStickyKeysEnabled( mContext); InputSettings.setAccessibilityStickyKeysEnabled(mContext, !stickyKeysEnabled); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS); return true; } } break; case KeyEvent.KEYCODE_6: if (InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean slowKeysEnabled = InputSettings.isAccessibilitySlowKeysEnabled(mContext); InputSettings.setAccessibilitySlowKeysThreshold(mContext, slowKeysEnabled ? 0 : InputSettings.DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS); return true; } } break; case KeyEvent.KEYCODE_DEL: if (newBugreportKeyboardShortcut()) { if (mEnableBugReportKeyboardShortcut && firstDown Loading Loading @@ -4053,6 +4116,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { .isAccessibilityShortcutAvailable(false); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK: return keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS: return InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS: return InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS: return InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS: return InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl(); default: return false; } Loading Loading @@ -4286,6 +4361,57 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (complete && isUserSetupComplete() && !keyguardOn && data != null && mModifierShortcutManager.launchApplication(data)) { dismissKeyboardShortcutsMenu(); } return true; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS: if (InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean bounceKeysEnabled = InputSettings.isAccessibilityBounceKeysEnabled( mContext); InputSettings.setAccessibilityBounceKeysThreshold(mContext, bounceKeysEnabled ? 0 : InputSettings.DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS); } return true; } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS: if (InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean mouseKeysEnabled = InputSettings.isAccessibilityMouseKeysEnabled( mContext); InputSettings.setAccessibilityMouseKeysEnabled(mContext, !mouseKeysEnabled); } return true; } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS: if (InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean stickyKeysEnabled = InputSettings.isAccessibilityStickyKeysEnabled(mContext); InputSettings.setAccessibilityStickyKeysEnabled(mContext, !stickyKeysEnabled); } return true; } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS: if (InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean slowKeysEnabled = InputSettings.isAccessibilitySlowKeysEnabled(mContext); InputSettings.setAccessibilitySlowKeysThreshold(mContext, slowKeysEnabled ? 0 : InputSettings.DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS); } return true; } break; Loading services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java +83 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAV import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE; import static com.android.server.policy.PhoneWindowManager.SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL; import android.hardware.input.InputSettings; import android.hardware.input.KeyGestureEvent; import android.os.RemoteException; import android.platform.test.annotations.DisableFlags; Loading Loading @@ -405,6 +406,36 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { META_ON | ALT_ON); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_MOUSE_KEYS}) @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER) public void testKeyboardAccessibilityToggleShortcutPress() { testShortcutInternal("Meta + Alt + 3 -> Toggle Bounce Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_3}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS, KeyEvent.KEYCODE_3, META_ON | ALT_ON); testShortcutInternal("Meta + Alt + 4 -> Toggle Mouse Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_4}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS, KeyEvent.KEYCODE_4, META_ON | ALT_ON); testShortcutInternal("Meta + Alt + 5 -> Toggle Sticky Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_5}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS, KeyEvent.KEYCODE_5, META_ON | ALT_ON); testShortcutInternal("Meta + Alt + 6 -> Toggle Slow Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_6}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS, KeyEvent.KEYCODE_6, META_ON | ALT_ON); } private void testShortcutInternal(String testName, int[] testKeys, @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { Loading Loading @@ -723,4 +754,56 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK)); mPhoneWindowManager.assertTalkBack(false); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG}) public void testKeyGestureToggleStickyKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS)); Assert.assertTrue(InputSettings.isAccessibilityStickyKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS)); Assert.assertFalse(InputSettings.isAccessibilityStickyKeysEnabled(mContext)); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG}) public void testKeyGestureToggleSlowKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS)); Assert.assertTrue(InputSettings.isAccessibilitySlowKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS)); Assert.assertFalse(InputSettings.isAccessibilitySlowKeysEnabled(mContext)); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_MOUSE_KEYS}) public void testKeyGestureToggleMouseKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS)); Assert.assertTrue(InputSettings.isAccessibilityMouseKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS)); Assert.assertFalse(InputSettings.isAccessibilityMouseKeysEnabled(mContext)); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG}) public void testKeyGestureToggleBounceKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS)); Assert.assertTrue(InputSettings.isAccessibilityBounceKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS)); Assert.assertFalse(InputSettings.isAccessibilityBounceKeysEnabled(mContext)); } } Loading
core/java/android/hardware/input/InputSettings.java +14 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,20 @@ public class InputSettings { @SuppressLint("UnflaggedApi") // TestApi without associated feature. public static final int DEFAULT_POINTER_SPEED = 0; /** * Bounce Keys Threshold: The default value of the threshold (500 ms). * * @hide */ public static final int DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS = 500; /** * Slow Keys Threshold: The default value of the threshold (500 ms). * * @hide */ public static final int DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS = 500; /** * The maximum allowed obscuring opacity by UID to propagate touches (0 <= x <= 1). * @hide Loading
core/java/android/hardware/input/KeyGestureEvent.java +16 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,10 @@ public final class KeyGestureEvent { public static final int KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS = 61; public static final int KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY = 62; public static final int KEY_GESTURE_TYPE_TOGGLE_TALKBACK = 63; public static final int KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS = 64; public static final int KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS = 65; public static final int KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS = 66; public static final int KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS = 67; public static final int FLAG_CANCELLED = 1; Loading Loading @@ -187,6 +191,10 @@ public final class KeyGestureEvent { KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS, KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY, KEY_GESTURE_TYPE_TOGGLE_TALKBACK, KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS, KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS, KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS, KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -733,6 +741,14 @@ public final class KeyGestureEvent { return "KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS"; case KEY_GESTURE_TYPE_TOGGLE_TALKBACK: return "KEY_GESTURE_TYPE_TOGGLE_TALKBACK"; case KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS"; case KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS"; case KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS"; case KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS: return "KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS"; default: return Integer.toHexString(value); } Loading
services/core/java/com/android/server/input/KeyGestureController.java +49 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.hardware.input.AidlKeyGestureEvent; import android.hardware.input.IKeyGestureEventListener; import android.hardware.input.IKeyGestureHandler; import android.hardware.input.InputManager; import android.hardware.input.InputSettings; import android.hardware.input.KeyGestureEvent; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -589,6 +590,54 @@ final class KeyGestureController { } } break; case KeyEvent.KEYCODE_3: if (InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_4: if (InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_5: if (InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_6: if (InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS, KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, focusedToken, /* flags = */0); } } break; case KeyEvent.KEYCODE_DEL: if (newBugreportKeyboardShortcut()) { if (firstDown && mEnableBugReportKeyboardShortcut && event.isMetaPressed() Loading
services/core/java/com/android/server/policy/PhoneWindowManager.java +126 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; import android.hardware.input.AppLaunchData; import android.hardware.input.InputManager; import android.hardware.input.InputSettings; import android.hardware.input.KeyGestureEvent; import android.media.AudioManager; import android.media.AudioManagerInternal; Loading Loading @@ -3617,6 +3618,68 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } break; case KeyEvent.KEYCODE_3: if (InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean bounceKeysEnabled = InputSettings.isAccessibilityBounceKeysEnabled( mContext); InputSettings.setAccessibilityBounceKeysThreshold(mContext, bounceKeysEnabled ? 0 : InputSettings.DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS); return true; } } break; case KeyEvent.KEYCODE_4: if (InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean mouseKeysEnabled = InputSettings.isAccessibilityMouseKeysEnabled( mContext); InputSettings.setAccessibilityMouseKeysEnabled(mContext, !mouseKeysEnabled); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS); return true; } } break; case KeyEvent.KEYCODE_5: if (InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean stickyKeysEnabled = InputSettings.isAccessibilityStickyKeysEnabled( mContext); InputSettings.setAccessibilityStickyKeysEnabled(mContext, !stickyKeysEnabled); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS); return true; } } break; case KeyEvent.KEYCODE_6: if (InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (firstDown && event.isMetaPressed() && event.isAltPressed()) { final boolean slowKeysEnabled = InputSettings.isAccessibilitySlowKeysEnabled(mContext); InputSettings.setAccessibilitySlowKeysThreshold(mContext, slowKeysEnabled ? 0 : InputSettings.DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS); notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS); return true; } } break; case KeyEvent.KEYCODE_DEL: if (newBugreportKeyboardShortcut()) { if (mEnableBugReportKeyboardShortcut && firstDown Loading Loading @@ -4053,6 +4116,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { .isAccessibilityShortcutAvailable(false); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK: return keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS: return InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS: return InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS: return InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl(); case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS: return InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl(); default: return false; } Loading Loading @@ -4286,6 +4361,57 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (complete && isUserSetupComplete() && !keyguardOn && data != null && mModifierShortcutManager.launchApplication(data)) { dismissKeyboardShortcutsMenu(); } return true; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS: if (InputSettings.isAccessibilityBounceKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean bounceKeysEnabled = InputSettings.isAccessibilityBounceKeysEnabled( mContext); InputSettings.setAccessibilityBounceKeysThreshold(mContext, bounceKeysEnabled ? 0 : InputSettings.DEFAULT_BOUNCE_KEYS_THRESHOLD_MILLIS); } return true; } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS: if (InputSettings.isAccessibilityMouseKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean mouseKeysEnabled = InputSettings.isAccessibilityMouseKeysEnabled( mContext); InputSettings.setAccessibilityMouseKeysEnabled(mContext, !mouseKeysEnabled); } return true; } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS: if (InputSettings.isAccessibilityStickyKeysFeatureEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean stickyKeysEnabled = InputSettings.isAccessibilityStickyKeysEnabled(mContext); InputSettings.setAccessibilityStickyKeysEnabled(mContext, !stickyKeysEnabled); } return true; } break; case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS: if (InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled() && keyboardA11yShortcutControl()) { if (complete) { final boolean slowKeysEnabled = InputSettings.isAccessibilitySlowKeysEnabled(mContext); InputSettings.setAccessibilitySlowKeysThreshold(mContext, slowKeysEnabled ? 0 : InputSettings.DEFAULT_SLOW_KEYS_THRESHOLD_MILLIS); } return true; } break; Loading
services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java +83 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAV import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE; import static com.android.server.policy.PhoneWindowManager.SETTINGS_KEY_BEHAVIOR_NOTIFICATION_PANEL; import android.hardware.input.InputSettings; import android.hardware.input.KeyGestureEvent; import android.os.RemoteException; import android.platform.test.annotations.DisableFlags; Loading Loading @@ -405,6 +406,36 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { META_ON | ALT_ON); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_MOUSE_KEYS}) @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER) public void testKeyboardAccessibilityToggleShortcutPress() { testShortcutInternal("Meta + Alt + 3 -> Toggle Bounce Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_3}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS, KeyEvent.KEYCODE_3, META_ON | ALT_ON); testShortcutInternal("Meta + Alt + 4 -> Toggle Mouse Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_4}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS, KeyEvent.KEYCODE_4, META_ON | ALT_ON); testShortcutInternal("Meta + Alt + 5 -> Toggle Sticky Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_5}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS, KeyEvent.KEYCODE_5, META_ON | ALT_ON); testShortcutInternal("Meta + Alt + 6 -> Toggle Slow Keys", new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_6}, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS, KeyEvent.KEYCODE_6, META_ON | ALT_ON); } private void testShortcutInternal(String testName, int[] testKeys, @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { Loading Loading @@ -723,4 +754,56 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK)); mPhoneWindowManager.assertTalkBack(false); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_STICKY_KEYS_FLAG}) public void testKeyGestureToggleStickyKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS)); Assert.assertTrue(InputSettings.isAccessibilityStickyKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_STICKY_KEYS)); Assert.assertFalse(InputSettings.isAccessibilityStickyKeysEnabled(mContext)); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SLOW_KEYS_FLAG}) public void testKeyGestureToggleSlowKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS)); Assert.assertTrue(InputSettings.isAccessibilitySlowKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_SLOW_KEYS)); Assert.assertFalse(InputSettings.isAccessibilitySlowKeysEnabled(mContext)); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_MOUSE_KEYS}) public void testKeyGestureToggleMouseKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS)); Assert.assertTrue(InputSettings.isAccessibilityMouseKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MOUSE_KEYS)); Assert.assertFalse(InputSettings.isAccessibilityMouseKeysEnabled(mContext)); } @Test @EnableFlags({com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL, com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_BOUNCE_KEYS_FLAG}) public void testKeyGestureToggleBounceKeys() { Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS)); Assert.assertTrue(InputSettings.isAccessibilityBounceKeysEnabled(mContext)); Assert.assertTrue( sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_BOUNCE_KEYS)); Assert.assertFalse(InputSettings.isAccessibilityBounceKeysEnabled(mContext)); } }