diff --git a/app/src/main/java/com/droiddeck/launcher/input/PadBridge.java b/app/src/main/java/com/droiddeck/launcher/input/PadBridge.java index 7584bf0d1..bdc3ff173 100644 --- a/app/src/main/java/com/droiddeck/launcher/input/PadBridge.java +++ b/app/src/main/java/com/droiddeck/launcher/input/PadBridge.java @@ -146,9 +146,15 @@ public final class PadBridge { } } + static boolean isSystemVirtualInputName(String name) { + if (name == null) return false; + String lower = name.trim().toLowerCase(java.util.Locale.ROOT); + return lower.startsWith("uinput-") || lower.startsWith("uinput_"); + } + public static boolean isFromController(InputDevice device) { if (device == null) return false; - if (device.isVirtual()) return false; + if (device.isVirtual() || isSystemVirtualInputName(device.getName())) return false; int sources = device.getSources(); if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) return true; if ((sources & InputDevice.SOURCE_JOYSTICK) != InputDevice.SOURCE_JOYSTICK) return false; @@ -165,7 +171,7 @@ public final class PadBridge { public static boolean isControllerKeyEvent(KeyEvent event) { InputDevice device = event.getDevice(); - if (device == null || device.isVirtual()) return false; + if (device == null || device.isVirtual() || isSystemVirtualInputName(device.getName())) return false; if (KeyEvent.isGamepadButton(event.getKeyCode())) { return device.supportsSource(InputDevice.SOURCE_GAMEPAD) || device.supportsSource(InputDevice.SOURCE_JOYSTICK); @@ -190,6 +196,7 @@ public final class PadBridge { public static boolean isControllerMotionEvent(MotionEvent event) { InputDevice device = event.getDevice(); return event.isFromSource(InputDevice.SOURCE_JOYSTICK) && device != null && !device.isVirtual() + && !isSystemVirtualInputName(device.getName()) && (device.supportsSource(InputDevice.SOURCE_GAMEPAD) || device.supportsSource(InputDevice.SOURCE_JOYSTICK)); } diff --git a/app/src/test/java/com/droiddeck/launcher/input/PadBridgeRoutingTest.kt b/app/src/test/java/com/droiddeck/launcher/input/PadBridgeRoutingTest.kt index 5c165b5a6..1d2e1a10e 100644 --- a/app/src/test/java/com/droiddeck/launcher/input/PadBridgeRoutingTest.kt +++ b/app/src/test/java/com/droiddeck/launcher/input/PadBridgeRoutingTest.kt @@ -71,6 +71,17 @@ class PadBridgeRoutingTest { InputDevice.KEYBOARD_TYPE_NONE, id = -1) assertTrue(virtual.isVirtual) assertFalse(PadBridge.isFromController(virtual)) + for (uinputName in listOf("uinput-xiaomi", "uinput-fpc", "uinput_nav")) { + val phantom = device( + InputDevice.SOURCE_GAMEPAD or InputDevice.SOURCE_JOYSTICK, + InputDevice.KEYBOARD_TYPE_NONE, + name = uinputName, + ) + assertFalse(phantom.isVirtual) + assertFalse(PadBridge.isFromController(phantom)) + assertFalse(PadBridge.isControllerKeyEvent(key(phantom, KeyEvent.KEYCODE_BUTTON_A, KeyEvent.ACTION_DOWN))) + } + assertFalse(PadBridge.anyControllerConnected()) } @Test fun keyAndMotionOwnershipDoesNotFollowEverySourceOnTheDevice() { @@ -146,8 +157,8 @@ class PadBridgeRoutingTest { private var nextId = 10 private fun device(sources: Int, type: Int, keys: IntArray = intArrayOf(KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_DPAD_UP), - rangeSource: Int? = null, axis: Int = MotionEvent.AXIS_X, id: Int = nextId++): InputDevice { - val builder = InputDeviceBuilder.newBuilder().setId(id).setName("routing fixture $id") + rangeSource: Int? = null, axis: Int = MotionEvent.AXIS_X, id: Int = nextId++, name: String = "routing fixture $id"): InputDevice { + val builder = InputDeviceBuilder.newBuilder().setId(id).setName(name) .setDescriptor("routing-$id").setExternal(true).setSources(sources).setKeyboardType(type) .setKeyCharacterMap(KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD)) if (rangeSource != null) builder.addMotionRange(axis, rangeSource, -1f, 1f, 0f, 0f, 0f)