Shift major shortcut handling from PWM to IMS

Use KeyGestureHandler APIs to shift shortcut and system event
trigerring to IMS and the handling to various system components

Test: atest InputTests
Test: atest WmTests
Bug: 358569822
Flag: com.android.hardware.input.use_key_gesture_event_handler
Change-Id: I03f4af47b180ab05fb92b78955ce2f2096707d7b
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index f3e040a..6742cbe 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -39,6 +39,7 @@
         "flag-junit",
         "frameworks-base-testutils",
         "hamcrest-library",
+        "junit-params",
         "kotlin-test",
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index e126797..28550cd 100644
--- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -25,19 +25,27 @@
 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.test.TestLooper
 import android.platform.test.annotations.Presubmit
 import android.view.InputDevice
+import android.view.KeyCharacterMap
 import android.view.KeyEvent
 import androidx.test.core.app.ApplicationProvider
+import com.android.internal.annotations.Keep
 import com.android.internal.util.FrameworkStatsLog
 import com.android.modules.utils.testing.ExtendedMockitoRule
+import junitparams.JUnitParamsRunner
+import junitparams.Parameters
+import org.junit.Assert.assertArrayEquals
 import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
+import org.junit.runner.RunWith
 import org.mockito.Mock
 import org.mockito.Mockito
 
@@ -48,6 +56,7 @@
  * atest InputTests:KeyGestureControllerTests
  */
 @Presubmit
+@RunWith(JUnitParamsRunner::class)
 class KeyGestureControllerTests {
 
     companion object {
@@ -59,6 +68,16 @@
             .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_HOME)
             .setAction(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             .build()
+        val MODIFIER = mapOf(
+            KeyEvent.KEYCODE_CTRL_LEFT to (KeyEvent.META_CTRL_LEFT_ON or KeyEvent.META_CTRL_ON),
+            KeyEvent.KEYCODE_CTRL_RIGHT to (KeyEvent.META_CTRL_RIGHT_ON or KeyEvent.META_CTRL_ON),
+            KeyEvent.KEYCODE_ALT_LEFT to (KeyEvent.META_ALT_LEFT_ON or KeyEvent.META_ALT_ON),
+            KeyEvent.KEYCODE_ALT_RIGHT to (KeyEvent.META_ALT_RIGHT_ON or KeyEvent.META_ALT_ON),
+            KeyEvent.KEYCODE_SHIFT_LEFT to (KeyEvent.META_SHIFT_LEFT_ON or KeyEvent.META_SHIFT_ON),
+            KeyEvent.KEYCODE_SHIFT_RIGHT to (KeyEvent.META_SHIFT_RIGHT_ON or KeyEvent.META_SHIFT_ON),
+            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),
+        )
     }
 
     @JvmField
@@ -75,6 +94,7 @@
     private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
     private lateinit var testLooper: TestLooper
     private var events = mutableListOf<KeyGestureEvent>()
+    private var handleEvents = mutableListOf<KeyGestureEvent>()
 
     @Before
     fun setup() {
@@ -184,6 +204,440 @@
         )
     }
 
+    class TestData(
+        val name: String,
+        val keys: IntArray,
+        val expectedKeyGestureType: Int,
+        val expectedKeys: IntArray,
+        val expectedModifierState: Int,
+        val expectedActions: IntArray,
+    ) {
+        override fun toString(): String = name
+    }
+
+    @Keep
+    private fun keyGestureEventHandlerTestArguments(): Array<TestData> {
+        return arrayOf(
+            TestData(
+                "META + A -> Launch Assistant",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_A),
+                KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT,
+                intArrayOf(KeyEvent.KEYCODE_A),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "RECENT_APPS -> Show Overview",
+                intArrayOf(KeyEvent.KEYCODE_RECENT_APPS),
+                KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS,
+                intArrayOf(KeyEvent.KEYCODE_RECENT_APPS),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "APP_SWITCH -> App Switch",
+                intArrayOf(KeyEvent.KEYCODE_APP_SWITCH),
+                KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH,
+                intArrayOf(KeyEvent.KEYCODE_APP_SWITCH),
+                0,
+                intArrayOf(
+                    KeyGestureEvent.ACTION_GESTURE_START,
+                    KeyGestureEvent.ACTION_GESTURE_COMPLETE
+                )
+            ),
+            TestData(
+                "META + H -> Go Home",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_H),
+                KeyGestureEvent.KEY_GESTURE_TYPE_HOME,
+                intArrayOf(KeyEvent.KEYCODE_H),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + ENTER -> Go Home",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_ENTER),
+                KeyGestureEvent.KEY_GESTURE_TYPE_HOME,
+                intArrayOf(KeyEvent.KEYCODE_ENTER),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + I -> Launch System Settings",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_I),
+                KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_SYSTEM_SETTINGS,
+                intArrayOf(KeyEvent.KEYCODE_I),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + L -> Lock",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_L),
+                KeyGestureEvent.KEY_GESTURE_TYPE_LOCK_SCREEN,
+                intArrayOf(KeyEvent.KEYCODE_L),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + N -> Toggle Notification",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_N),
+                KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
+                intArrayOf(KeyEvent.KEYCODE_N),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + CTRL + S -> Take Screenshot",
+                intArrayOf(
+                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_S
+                ),
+                KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT,
+                intArrayOf(KeyEvent.KEYCODE_S),
+                KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + DEL -> Back",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_DEL),
+                KeyGestureEvent.KEY_GESTURE_TYPE_BACK,
+                intArrayOf(KeyEvent.KEYCODE_DEL),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + ESC -> Back",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_ESCAPE),
+                KeyGestureEvent.KEY_GESTURE_TYPE_BACK,
+                intArrayOf(KeyEvent.KEYCODE_ESCAPE),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + DPAD_LEFT -> Back",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_DPAD_LEFT),
+                KeyGestureEvent.KEY_GESTURE_TYPE_BACK,
+                intArrayOf(KeyEvent.KEYCODE_DPAD_LEFT),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + CTRL + DPAD_UP -> Multi Window Navigation",
+                intArrayOf(
+                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_DPAD_UP
+                ),
+                KeyGestureEvent.KEY_GESTURE_TYPE_MULTI_WINDOW_NAVIGATION,
+                intArrayOf(KeyEvent.KEYCODE_DPAD_UP),
+                KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + CTRL + DPAD_DOWN -> Desktop Mode",
+                intArrayOf(
+                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_DPAD_DOWN
+                ),
+                KeyGestureEvent.KEY_GESTURE_TYPE_DESKTOP_MODE,
+                intArrayOf(KeyEvent.KEYCODE_DPAD_DOWN),
+                KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + CTRL + DPAD_LEFT -> Splitscreen Navigation Left",
+                intArrayOf(
+                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_DPAD_LEFT
+                ),
+                KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_LEFT,
+                intArrayOf(KeyEvent.KEYCODE_DPAD_LEFT),
+                KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + CTRL + DPAD_RIGHT -> Splitscreen Navigation Right",
+                intArrayOf(
+                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_DPAD_RIGHT
+                ),
+                KeyGestureEvent.KEY_GESTURE_TYPE_SPLIT_SCREEN_NAVIGATION_RIGHT,
+                intArrayOf(KeyEvent.KEYCODE_DPAD_RIGHT),
+                KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + ALT + DPAD_LEFT -> Change Splitscreen Focus Left",
+                intArrayOf(
+                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_ALT_LEFT,
+                    KeyEvent.KEYCODE_DPAD_LEFT
+                ),
+                KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT,
+                intArrayOf(KeyEvent.KEYCODE_DPAD_LEFT),
+                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + CTRL + DPAD_RIGHT -> Change Splitscreen Focus Right",
+                intArrayOf(
+                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_ALT_LEFT,
+                    KeyEvent.KEYCODE_DPAD_RIGHT
+                ),
+                KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT,
+                intArrayOf(KeyEvent.KEYCODE_DPAD_RIGHT),
+                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "BRIGHTNESS_UP -> Brightness Up",
+                intArrayOf(KeyEvent.KEYCODE_BRIGHTNESS_UP),
+                KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_UP,
+                intArrayOf(KeyEvent.KEYCODE_BRIGHTNESS_UP),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "BRIGHTNESS_DOWN -> Brightness Down",
+                intArrayOf(KeyEvent.KEYCODE_BRIGHTNESS_DOWN),
+                KeyGestureEvent.KEY_GESTURE_TYPE_BRIGHTNESS_DOWN,
+                intArrayOf(KeyEvent.KEYCODE_BRIGHTNESS_DOWN),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "KEYBOARD_BACKLIGHT_UP -> Keyboard Backlight Up",
+                intArrayOf(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP),
+                KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_UP,
+                intArrayOf(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_UP),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "KEYBOARD_BACKLIGHT_DOWN -> Keyboard Backlight Down",
+                intArrayOf(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN),
+                KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_DOWN,
+                intArrayOf(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "KEYBOARD_BACKLIGHT_TOGGLE -> Keyboard Backlight Toggle",
+                intArrayOf(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE),
+                KeyGestureEvent.KEY_GESTURE_TYPE_KEYBOARD_BACKLIGHT_TOGGLE,
+                intArrayOf(KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_TOGGLE),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "ALL_APPS -> Open App Drawer",
+                intArrayOf(KeyEvent.KEYCODE_ALL_APPS),
+                KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS,
+                intArrayOf(KeyEvent.KEYCODE_ALL_APPS),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "NOTIFICATION -> Toggle Notification Panel",
+                intArrayOf(KeyEvent.KEYCODE_NOTIFICATION),
+                KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL,
+                intArrayOf(KeyEvent.KEYCODE_NOTIFICATION),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "LANGUAGE_SWITCH -> Switch Language Forward",
+                intArrayOf(KeyEvent.KEYCODE_LANGUAGE_SWITCH),
+                KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH,
+                intArrayOf(KeyEvent.KEYCODE_LANGUAGE_SWITCH),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "SHIFT + LANGUAGE_SWITCH -> Switch Language Backward",
+                intArrayOf(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_LANGUAGE_SWITCH),
+                KeyGestureEvent.KEY_GESTURE_TYPE_LANGUAGE_SWITCH,
+                intArrayOf(KeyEvent.KEYCODE_LANGUAGE_SWITCH),
+                KeyEvent.META_SHIFT_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "SCREENSHOT -> Take Screenshot",
+                intArrayOf(KeyEvent.KEYCODE_SCREENSHOT),
+                KeyGestureEvent.KEY_GESTURE_TYPE_TAKE_SCREENSHOT,
+                intArrayOf(KeyEvent.KEYCODE_SCREENSHOT),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META -> Open Apps Drawer",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT),
+                KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS,
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + ALT -> Toggle Caps Lock",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_ALT_LEFT),
+                KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK,
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_ALT_LEFT),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "ALT + META -> Toggle Caps Lock",
+                intArrayOf(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_META_LEFT),
+                KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK,
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_ALT_LEFT),
+                0,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "META + TAB -> Open Overview",
+                intArrayOf(KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_TAB),
+                KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS,
+                intArrayOf(KeyEvent.KEYCODE_TAB),
+                KeyEvent.META_META_ON,
+                intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+            ),
+            TestData(
+                "ALT + TAB -> Toggle Recent Apps Switcher",
+                intArrayOf(KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_TAB),
+                KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER,
+                intArrayOf(KeyEvent.KEYCODE_TAB),
+                KeyEvent.META_ALT_ON,
+                intArrayOf(
+                    KeyGestureEvent.ACTION_GESTURE_START,
+                    KeyGestureEvent.ACTION_GESTURE_COMPLETE
+                )
+            ),
+        )
+    }
+
+    @Test
+    @Parameters(method = "keyGestureEventHandlerTestArguments")
+    fun testKeyGestures(test: TestData) {
+        val handler = KeyGestureHandler { event, _ ->
+            handleEvents.add(KeyGestureEvent(event))
+            true
+        }
+        keyGestureController.registerKeyGestureHandler(handler, 0)
+        handleEvents.clear()
+
+        sendKeys(test.keys, /* assertAllConsumed = */ false)
+
+        assertEquals(
+            "Test: $test doesn't produce correct number of key gesture events",
+            test.expectedActions.size,
+            handleEvents.size
+        )
+        for (i in handleEvents.indices) {
+            val event = handleEvents[i]
+            assertArrayEquals(
+                "Test: $test doesn't produce correct key gesture keycodes",
+                test.expectedKeys,
+                event.keycodes
+            )
+            assertEquals(
+                "Test: $test doesn't produce correct key gesture modifier state",
+                test.expectedModifierState,
+                event.modifierState
+            )
+            assertEquals(
+                "Test: $test doesn't produce correct key gesture type",
+                test.expectedKeyGestureType,
+                event.keyGestureType
+            )
+            assertEquals(
+                "Test: $test doesn't produce correct key gesture action",
+                test.expectedActions[i],
+                event.action
+            )
+        }
+
+        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 }
+        keyGestureController.registerKeyGestureHandler(handler, 0)
+
+        for (key in testKeys) {
+            sendKeys(intArrayOf(key), /* assertAllConsumed = */ true)
+        }
+    }
+
+    private fun sendKeys(testKeys: IntArray, assertAllConsumed: Boolean) {
+        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 /*flags*/, InputDevice.SOURCE_KEYBOARD
+            )
+            val consumed =
+                keyGestureController.interceptKeyBeforeDispatching(null, downEvent, 0) == -1L
+            if (assertAllConsumed) {
+                assertTrue(
+                    "interceptKeyBeforeDispatching should consume all events $downEvent",
+                    consumed
+                )
+            }
+            metaState = metaState or MODIFIER.getOrDefault(key, 0)
+
+            downEvent.recycle()
+            testLooper.dispatchAll()
+        }
+
+        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 /*flags*/, InputDevice.SOURCE_KEYBOARD
+            )
+            val consumed =
+                keyGestureController.interceptKeyBeforeDispatching(null, upEvent, 0) == -1L
+            if (assertAllConsumed) {
+                assertTrue(
+                    "interceptKeyBeforeDispatching should consume all events $upEvent",
+                    consumed
+                )
+            }
+
+            upEvent.recycle()
+            testLooper.dispatchAll()
+        }
+    }
+
     inner class KeyGestureEventListener : IKeyGestureEventListener.Stub() {
         override fun onKeyGestureEvent(event: AidlKeyGestureEvent) {
             events.add(KeyGestureEvent(event))