Loading services/core/java/com/android/server/input/InputGestureManager.java +24 −0 Original line number Diff line number Diff line Loading @@ -17,10 +17,13 @@ package com.android.server.input; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.hardware.input.InputGestureData; import android.hardware.input.InputManager; import android.util.IndentingPrintWriter; import android.util.SparseArray; import android.view.KeyEvent; import com.android.internal.annotations.GuardedBy; Loading @@ -40,6 +43,10 @@ import java.util.Objects; final class InputGestureManager { private static final String TAG = "InputGestureManager"; private static final int KEY_GESTURE_META_MASK = KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON | KeyEvent.META_META_ON; @GuardedBy("mCustomInputGestures") private final SparseArray<Map<InputGestureData.Trigger, InputGestureData>> mCustomInputGestures = new SparseArray<>(); Loading Loading @@ -96,6 +103,23 @@ final class InputGestureManager { } } @Nullable public InputGestureData getCustomGestureForKeyEvent(@UserIdInt int userId, KeyEvent event) { final int keyCode = event.getKeyCode(); if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { return null; } synchronized (mCustomInputGestures) { Map<InputGestureData.Trigger, InputGestureData> customGestures = mCustomInputGestures.get(userId); if (customGestures == null) { return null; } int modifierState = event.getMetaState() & KEY_GESTURE_META_MASK; return customGestures.get(InputGestureData.createKeyTrigger(keyCode, modifierState)); } } public void dump(IndentingPrintWriter ipw) { ipw.println("InputGestureManager:"); ipw.increaseIndent(); Loading services/core/java/com/android/server/input/InputManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -3022,6 +3022,7 @@ public class InputManagerService extends IInputManager.Stub private void handleCurrentUserChanged(@UserIdInt int userId) { mCurrentUserId = userId; mKeyGestureController.setCurrentUserId(userId); } /** Loading services/core/java/com/android/server/input/KeyGestureController.java +121 −78 File changed.Preview size limit exceeded, changes collapsed. Show changes tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt +65 −1 Original line number Diff line number Diff line Loading @@ -22,8 +22,10 @@ import android.content.pm.PackageManager import android.content.res.Resources import android.hardware.input.IInputManager import android.hardware.input.AidlKeyGestureEvent import android.hardware.input.AppLaunchData import android.hardware.input.IKeyGestureEventListener import android.hardware.input.IKeyGestureHandler import android.hardware.input.InputGestureData import android.hardware.input.InputManager import android.hardware.input.InputManagerGlobal import android.hardware.input.KeyGestureEvent Loading Loading @@ -232,7 +234,7 @@ class KeyGestureControllerTests { keyGestureController.handleKeyGesture(/* deviceId = */ 0, intArrayOf(KeyEvent.KEYCODE_HOME), /* modifierState = */ 0, KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyGestureEvent.ACTION_GESTURE_COMPLETE, /* displayId */ 0, /* focusedToken = */ null, /* flags = */ 0 /* focusedToken = */ null, /* flags = */ 0, /* appLaunchData = */null ) assertEquals( Loading @@ -259,6 +261,7 @@ class KeyGestureControllerTests { val expectedKeys: IntArray, val expectedModifierState: Int, val expectedActions: IntArray, val expectedAppLaunchData: AppLaunchData? = null, ) { override fun toString(): String = name } Loading Loading @@ -1055,6 +1058,62 @@ class KeyGestureControllerTests { testKeyGestureInternal(keyGestureController, test) } @Keep private fun customInputGesturesTestArguments(): Array<TestData> { return arrayOf( TestData( "META + ALT + Q -> Go Home", intArrayOf( KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_Q ), KeyGestureEvent.KEY_GESTURE_TYPE_HOME, intArrayOf(KeyEvent.KEYCODE_Q), KeyEvent.META_META_ON or KeyEvent.META_ALT_ON, intArrayOf( KeyGestureEvent.ACTION_GESTURE_COMPLETE ) ), TestData( "META + ALT + Q -> Launch app", intArrayOf( KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_Q ), KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, intArrayOf(KeyEvent.KEYCODE_Q), KeyEvent.META_CTRL_ON or KeyEvent.META_SHIFT_ON, intArrayOf( KeyGestureEvent.ACTION_GESTURE_COMPLETE ), AppLaunchData.createLaunchDataForComponent("com.test", "com.test.BookmarkTest") ), ) } @Test @Parameters(method = "customInputGesturesTestArguments") fun testCustomKeyGestures(test: TestData) { val keyGestureController = KeyGestureController(context, testLooper.looper) val builder = InputGestureData.Builder() .setKeyGestureType(test.expectedKeyGestureType) .setTrigger( InputGestureData.createKeyTrigger( test.expectedKeys[0], test.expectedModifierState ) ); if (test.expectedAppLaunchData != null) { builder.setAppLaunchData(test.expectedAppLaunchData) } val inputGestureData = builder.build(); keyGestureController.addCustomInputGesture(0, inputGestureData.aidlData) testKeyGestureInternal(keyGestureController, test) } private fun testKeyGestureInternal(keyGestureController: KeyGestureController, test: TestData) { var handleEvents = mutableListOf<KeyGestureEvent>() val handler = KeyGestureHandler { event, _ -> Loading Loading @@ -1093,6 +1152,11 @@ class KeyGestureControllerTests { test.expectedActions[i], event.action ) assertEquals( "Test: $test doesn't produce correct app launch data", test.expectedAppLaunchData, event.appLaunchData ) } keyGestureController.unregisterKeyGestureHandler(handler, 0) Loading Loading
services/core/java/com/android/server/input/InputGestureManager.java +24 −0 Original line number Diff line number Diff line Loading @@ -17,10 +17,13 @@ package com.android.server.input; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.hardware.input.InputGestureData; import android.hardware.input.InputManager; import android.util.IndentingPrintWriter; import android.util.SparseArray; import android.view.KeyEvent; import com.android.internal.annotations.GuardedBy; Loading @@ -40,6 +43,10 @@ import java.util.Objects; final class InputGestureManager { private static final String TAG = "InputGestureManager"; private static final int KEY_GESTURE_META_MASK = KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON | KeyEvent.META_META_ON; @GuardedBy("mCustomInputGestures") private final SparseArray<Map<InputGestureData.Trigger, InputGestureData>> mCustomInputGestures = new SparseArray<>(); Loading Loading @@ -96,6 +103,23 @@ final class InputGestureManager { } } @Nullable public InputGestureData getCustomGestureForKeyEvent(@UserIdInt int userId, KeyEvent event) { final int keyCode = event.getKeyCode(); if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { return null; } synchronized (mCustomInputGestures) { Map<InputGestureData.Trigger, InputGestureData> customGestures = mCustomInputGestures.get(userId); if (customGestures == null) { return null; } int modifierState = event.getMetaState() & KEY_GESTURE_META_MASK; return customGestures.get(InputGestureData.createKeyTrigger(keyCode, modifierState)); } } public void dump(IndentingPrintWriter ipw) { ipw.println("InputGestureManager:"); ipw.increaseIndent(); Loading
services/core/java/com/android/server/input/InputManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -3022,6 +3022,7 @@ public class InputManagerService extends IInputManager.Stub private void handleCurrentUserChanged(@UserIdInt int userId) { mCurrentUserId = userId; mKeyGestureController.setCurrentUserId(userId); } /** Loading
services/core/java/com/android/server/input/KeyGestureController.java +121 −78 File changed.Preview size limit exceeded, changes collapsed. Show changes
tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt +65 −1 Original line number Diff line number Diff line Loading @@ -22,8 +22,10 @@ import android.content.pm.PackageManager import android.content.res.Resources import android.hardware.input.IInputManager import android.hardware.input.AidlKeyGestureEvent import android.hardware.input.AppLaunchData import android.hardware.input.IKeyGestureEventListener import android.hardware.input.IKeyGestureHandler import android.hardware.input.InputGestureData import android.hardware.input.InputManager import android.hardware.input.InputManagerGlobal import android.hardware.input.KeyGestureEvent Loading Loading @@ -232,7 +234,7 @@ class KeyGestureControllerTests { keyGestureController.handleKeyGesture(/* deviceId = */ 0, intArrayOf(KeyEvent.KEYCODE_HOME), /* modifierState = */ 0, KeyGestureEvent.KEY_GESTURE_TYPE_HOME, KeyGestureEvent.ACTION_GESTURE_COMPLETE, /* displayId */ 0, /* focusedToken = */ null, /* flags = */ 0 /* focusedToken = */ null, /* flags = */ 0, /* appLaunchData = */null ) assertEquals( Loading @@ -259,6 +261,7 @@ class KeyGestureControllerTests { val expectedKeys: IntArray, val expectedModifierState: Int, val expectedActions: IntArray, val expectedAppLaunchData: AppLaunchData? = null, ) { override fun toString(): String = name } Loading Loading @@ -1055,6 +1058,62 @@ class KeyGestureControllerTests { testKeyGestureInternal(keyGestureController, test) } @Keep private fun customInputGesturesTestArguments(): Array<TestData> { return arrayOf( TestData( "META + ALT + Q -> Go Home", intArrayOf( KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_Q ), KeyGestureEvent.KEY_GESTURE_TYPE_HOME, intArrayOf(KeyEvent.KEYCODE_Q), KeyEvent.META_META_ON or KeyEvent.META_ALT_ON, intArrayOf( KeyGestureEvent.ACTION_GESTURE_COMPLETE ) ), TestData( "META + ALT + Q -> Launch app", intArrayOf( KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_Q ), KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_APPLICATION, intArrayOf(KeyEvent.KEYCODE_Q), KeyEvent.META_CTRL_ON or KeyEvent.META_SHIFT_ON, intArrayOf( KeyGestureEvent.ACTION_GESTURE_COMPLETE ), AppLaunchData.createLaunchDataForComponent("com.test", "com.test.BookmarkTest") ), ) } @Test @Parameters(method = "customInputGesturesTestArguments") fun testCustomKeyGestures(test: TestData) { val keyGestureController = KeyGestureController(context, testLooper.looper) val builder = InputGestureData.Builder() .setKeyGestureType(test.expectedKeyGestureType) .setTrigger( InputGestureData.createKeyTrigger( test.expectedKeys[0], test.expectedModifierState ) ); if (test.expectedAppLaunchData != null) { builder.setAppLaunchData(test.expectedAppLaunchData) } val inputGestureData = builder.build(); keyGestureController.addCustomInputGesture(0, inputGestureData.aidlData) testKeyGestureInternal(keyGestureController, test) } private fun testKeyGestureInternal(keyGestureController: KeyGestureController, test: TestData) { var handleEvents = mutableListOf<KeyGestureEvent>() val handler = KeyGestureHandler { event, _ -> Loading Loading @@ -1093,6 +1152,11 @@ class KeyGestureControllerTests { test.expectedActions[i], event.action ) assertEquals( "Test: $test doesn't produce correct app launch data", test.expectedAppLaunchData, event.appLaunchData ) } keyGestureController.unregisterKeyGestureHandler(handler, 0) Loading