From 2d84737f418f0d73a0d7f66cf3ca8a66c7c4bc0a Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 15 Apr 2022 15:51:01 +0200 Subject: [PATCH 1/2] Adapt event injection to Android 13 Using the "input" service results in a permission error in Android 13. Use the InputManager instance (retrieved by InputManager.getInstance()) instead. Fixes #3186 --- .../com/genymobile/scrcpy/wrappers/InputManager.java | 4 ++-- .../com/genymobile/scrcpy/wrappers/ServiceManager.java | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java index 6116899351..3ba4f97aa2 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java @@ -14,13 +14,13 @@ public final class InputManager { public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1; public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; - private final IInterface manager; + private final android.hardware.input.InputManager manager; private Method injectInputEventMethod; private boolean alternativeInjectInputEventMethod; private static Method setDisplayIdMethod; - public InputManager(IInterface manager) { + public InputManager(android.hardware.input.InputManager manager) { this.manager = manager; } diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java index 6f4b9c042c..ea2a078470 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java @@ -4,6 +4,7 @@ import android.os.IBinder; import android.os.IInterface; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @SuppressLint("PrivateApi,DiscouragedPrivateApi") @@ -56,7 +57,13 @@ public DisplayManager getDisplayManager() { public InputManager getInputManager() { if (inputManager == null) { - inputManager = new InputManager(getService("input", "android.hardware.input.IInputManager")); + try { + Method getInstanceMethod = android.hardware.input.InputManager.class.getDeclaredMethod("getInstance"); + android.hardware.input.InputManager im = (android.hardware.input.InputManager) getInstanceMethod.invoke(null); + inputManager = new InputManager(im); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new AssertionError(e); + } } return inputManager; } From 6cac0c32a2bc4c812c5b51ca108fe815f526ada8 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sat, 16 Apr 2022 09:28:24 +0200 Subject: [PATCH 2/2] Remove obsolete alternative injection method The previous commit replaced the IInterface instance (the "input" service) by the InputManager instance (retrieved by InputManager.getInstance()). Both define an "injectInputEvent" method, but the alternate version (probably) does not concern the InputManager. This reverts commit b7a06278fee0dbfbb18b651ad563d9fb0797c8bc. --- .../com/genymobile/scrcpy/wrappers/InputManager.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java index 3ba4f97aa2..e4ec7252ef 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java @@ -16,7 +16,6 @@ public final class InputManager { private final android.hardware.input.InputManager manager; private Method injectInputEventMethod; - private boolean alternativeInjectInputEventMethod; private static Method setDisplayIdMethod; @@ -26,12 +25,7 @@ public InputManager(android.hardware.input.InputManager manager) { private Method getInjectInputEventMethod() throws NoSuchMethodException { if (injectInputEventMethod == null) { - try { - injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class); - } catch (NoSuchMethodException e) { - injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class, int.class); - alternativeInjectInputEventMethod = true; - } + injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class); } return injectInputEventMethod; } @@ -39,10 +33,6 @@ private Method getInjectInputEventMethod() throws NoSuchMethodException { public boolean injectInputEvent(InputEvent inputEvent, int mode) { try { Method method = getInjectInputEventMethod(); - if (alternativeInjectInputEventMethod) { - // See - return (boolean) method.invoke(manager, inputEvent, mode, 0); - } return (boolean) method.invoke(manager, inputEvent, mode); } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { Ln.e("Could not invoke method", e);