diff options
| author | 2025-01-08 15:30:07 +0000 | |
|---|---|---|
| committer | 2025-01-09 04:40:24 -0800 | |
| commit | af01f6dff2792ce8c4b1817ce05964c96b1477a2 (patch) | |
| tree | 4b0c0b952243a37606964e7b1bd03fc6f780f54d | |
| parent | cdcdd9e97c6da6ef8b1e0e521ed695694cd701a5 (diff) | |
Add new API to check if a custom gesture trigger is available
In order to notify user that a key combination is already taken,
we need another API to check if a input gesture trigger is
available. This is a new UX request allowing user to pre-emptively
know if adding a custom gesture is allowed for a trigger or not.
Bug: 381063978
Test: atest InputTests
Flag: EXEMPT internal API addition only
Change-Id: Id579fa179acabc783ab6ca61bf34b8b74dc5e1af
7 files changed, 102 insertions, 7 deletions
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index ed510e467f82..2bb28a1b6b0b 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -266,6 +266,11 @@ interface IInputManager { @PermissionManuallyEnforced @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " + "android.Manifest.permission.MANAGE_KEY_GESTURES)") + AidlInputGestureData getInputGesture(int userId, in AidlInputGestureData.Trigger trigger); + + @PermissionManuallyEnforced + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " + + "android.Manifest.permission.MANAGE_KEY_GESTURES)") int addCustomInputGesture(int userId, in AidlInputGestureData data); @PermissionManuallyEnforced diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 10224c1be788..cf41e138047a 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -1480,6 +1480,30 @@ public final class InputManager { mGlobal.unregisterKeyGestureEventHandler(handler); } + /** + * Find an input gesture mapped to a particular trigger. + * + * @param trigger to find the input gesture for + * @return input gesture mapped to the provided trigger, {@code null} if none found + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES) + @UserHandleAware + @Nullable + public InputGestureData getInputGesture(@NonNull InputGestureData.Trigger trigger) { + try { + AidlInputGestureData result = mIm.getInputGesture(mContext.getUserId(), + trigger.getAidlTrigger()); + if (result == null) { + return null; + } + return new InputGestureData(result); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** Adds a new custom input gesture * * @param inputGestureData gesture data to add as custom gesture diff --git a/core/java/android/hardware/input/KeyGestureEvent.java b/core/java/android/hardware/input/KeyGestureEvent.java index 66d073fa791e..63bfef92d8ca 100644 --- a/core/java/android/hardware/input/KeyGestureEvent.java +++ b/core/java/android/hardware/input/KeyGestureEvent.java @@ -43,6 +43,9 @@ public final class KeyGestureEvent { private static final int LOG_EVENT_UNSPECIFIED = FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__UNSPECIFIED; + // Used as a placeholder to identify if a gesture is reserved for system + public static final int KEY_GESTURE_TYPE_SYSTEM_RESERVED = -1; + // These values should not change and values should not be re-used as this data is persisted to // long term storage and must be kept backwards compatible. public static final int KEY_GESTURE_TYPE_UNSPECIFIED = 0; @@ -143,6 +146,7 @@ public final class KeyGestureEvent { public static final int ACTION_GESTURE_COMPLETE = 2; @IntDef(prefix = "KEY_GESTURE_TYPE_", value = { + KEY_GESTURE_TYPE_SYSTEM_RESERVED, KEY_GESTURE_TYPE_UNSPECIFIED, KEY_GESTURE_TYPE_HOME, KEY_GESTURE_TYPE_RECENT_APPS, @@ -643,6 +647,8 @@ public final class KeyGestureEvent { private static String keyGestureTypeToString(@KeyGestureType int value) { switch (value) { + case KEY_GESTURE_TYPE_SYSTEM_RESERVED: + return "KEY_GESTURE_TYPE_SYSTEM_RESERVED"; case KEY_GESTURE_TYPE_UNSPECIFIED: return "KEY_GESTURE_TYPE_UNSPECIFIED"; case KEY_GESTURE_TYPE_HOME: diff --git a/services/core/java/com/android/server/input/InputGestureManager.java b/services/core/java/com/android/server/input/InputGestureManager.java index 9f785ac81398..ffa83ce254bb 100644 --- a/services/core/java/com/android/server/input/InputGestureManager.java +++ b/services/core/java/com/android/server/input/InputGestureManager.java @@ -308,6 +308,31 @@ final class InputGestureManager { } } + @Nullable + public InputGestureData getInputGesture(int userId, InputGestureData.Trigger trigger) { + synchronized (mGestureLock) { + if (mBlockListedTriggers.contains(trigger)) { + return new InputGestureData.Builder().setTrigger(trigger).setKeyGestureType( + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_RESERVED).build(); + } + if (trigger instanceof InputGestureData.KeyTrigger keyTrigger) { + if (KeyEvent.isModifierKey(keyTrigger.getKeycode()) || + KeyEvent.isSystemKey(keyTrigger.getKeycode())) { + return new InputGestureData.Builder().setTrigger(trigger).setKeyGestureType( + KeyGestureEvent.KEY_GESTURE_TYPE_SYSTEM_RESERVED).build(); + } + } + InputGestureData gestureData = mSystemShortcuts.get(trigger); + if (gestureData != null) { + return gestureData; + } + if (!mCustomInputGestures.contains(userId)) { + return null; + } + return mCustomInputGestures.get(userId).get(trigger); + } + } + @InputManager.CustomInputGestureResult public int addCustomInputGesture(int userId, InputGestureData newGesture) { synchronized (mGestureLock) { diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 559b4ae64e50..6ae9b5c10d7c 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -3061,6 +3061,16 @@ public class InputManagerService extends IInputManager.Stub @Override @PermissionManuallyEnforced + public AidlInputGestureData getInputGesture(@UserIdInt int userId, + @NonNull AidlInputGestureData.Trigger trigger) { + enforceManageKeyGesturePermission(); + + Objects.requireNonNull(trigger); + return mKeyGestureController.getInputGesture(userId, trigger); + } + + @Override + @PermissionManuallyEnforced public int addCustomInputGesture(@UserIdInt int userId, @NonNull AidlInputGestureData inputGestureData) { enforceManageKeyGesturePermission(); diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java index 5f7ad2797368..c5c1528a40f0 100644 --- a/services/core/java/com/android/server/input/KeyGestureController.java +++ b/services/core/java/com/android/server/input/KeyGestureController.java @@ -1069,6 +1069,18 @@ final class KeyGestureController { } @BinderThread + @Nullable + public AidlInputGestureData getInputGesture(@UserIdInt int userId, + @NonNull AidlInputGestureData.Trigger trigger) { + InputGestureData gestureData = mInputGestureManager.getInputGesture(userId, + InputGestureData.createTriggerFromAidlTrigger(trigger)); + if (gestureData == null) { + return null; + } + return gestureData.getAidlData(); + } + + @BinderThread @InputManager.CustomInputGestureResult public int addCustomInputGesture(@UserIdInt int userId, @NonNull AidlInputGestureData inputGestureData) { diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt index 4d7085feb98f..138251ab68a1 100644 --- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt +++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt @@ -59,6 +59,7 @@ import junitparams.Parameters import org.junit.After import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Rule @@ -1452,20 +1453,32 @@ class KeyGestureControllerTests { @Parameters(method = "customInputGesturesTestArguments") fun testCustomKeyGestures(test: TestData) { setupKeyGestureController() + val trigger = InputGestureData.createKeyTrigger( + test.expectedKeys[0], + test.expectedModifierState + ) val builder = InputGestureData.Builder() .setKeyGestureType(test.expectedKeyGestureType) - .setTrigger( - InputGestureData.createKeyTrigger( - test.expectedKeys[0], - test.expectedModifierState - ) - ) + .setTrigger(trigger) if (test.expectedAppLaunchData != null) { builder.setAppLaunchData(test.expectedAppLaunchData) } val inputGestureData = builder.build() - keyGestureController.addCustomInputGesture(0, inputGestureData.aidlData) + assertNull( + test.toString(), + keyGestureController.getInputGesture(0, trigger.aidlTrigger) + ) + assertEquals( + test.toString(), + InputManager.CUSTOM_INPUT_GESTURE_RESULT_SUCCESS, + keyGestureController.addCustomInputGesture(0, builder.build().aidlData) + ) + assertEquals( + test.toString(), + inputGestureData.aidlData, + keyGestureController.getInputGesture(0, trigger.aidlTrigger) + ) testKeyGestureInternal(test) } |