diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 4b7e362a..dd80a160 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -1,5 +1,8 @@ package com.genymobile.scrcpy; +import com.genymobile.scrcpy.wrappers.ServiceManager; + +import android.content.Intent; import android.os.Build; import android.os.SystemClock; import android.view.InputDevice; @@ -149,12 +152,12 @@ public class Controller { private boolean injectChar(char c) { if (options.useADBKeyboard()) { // Process latin keys the same way in order to provide same reaction speed. - try { - Process process = Runtime.getRuntime().exec("am broadcast -a ADB_INPUT_CHARS --eia chars " + String.valueOf((int) c)); - return process.waitFor() == 0; - } catch (Throwable throwable) { - return false; - } + Intent intent = new Intent(); + intent.setAction("ADB_INPUT_CHARS"); + int[] chars = {c}; + intent.putExtra("chars", chars); + device.sendBroadcast(intent); + return true; } else { String decomposed = KeyComposition.decompose(c); char[] chars = decomposed != null ? decomposed.toCharArray() : new char[]{c}; diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index a8fdf677..38d01645 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -8,6 +8,7 @@ import com.genymobile.scrcpy.wrappers.SurfaceControl; import com.genymobile.scrcpy.wrappers.WindowManager; import android.content.IOnPrimaryClipChangedListener; +import android.content.Intent; import android.graphics.Rect; import android.os.Build; import android.os.IBinder; @@ -273,4 +274,8 @@ public final class Device { public static ContentProvider createSettingsProvider() { return SERVICE_MANAGER.getActivityManager().createSettingsProvider(); } + + public void sendBroadcast(Intent intent) { + SERVICE_MANAGER.getActivityManager().sendBroadcast(intent); + } } diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java index 71967c50..3fe903e9 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ActivityManager.java @@ -2,7 +2,9 @@ package com.genymobile.scrcpy.wrappers; import com.genymobile.scrcpy.Ln; +import android.content.Intent; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.os.IInterface; @@ -16,6 +18,7 @@ public class ActivityManager { private Method getContentProviderExternalMethod; private boolean getContentProviderExternalMethodLegacy; private Method removeContentProviderExternalMethod; + private Method broadcastIntentMethod; public ActivityManager(IInterface manager) { this.manager = manager; @@ -42,6 +45,22 @@ public class ActivityManager { return removeContentProviderExternalMethod; } + private Method getBroadcastIntentMethod() throws NoSuchMethodException { + if (broadcastIntentMethod == null) { + try { + Class iApplicationThreadClass = Class.forName("android.app.IApplicationThread"); + Class iIntentReceiverClass = Class.forName("android.content.IIntentReceiver"); + broadcastIntentMethod = manager.getClass() + .getMethod("broadcastIntent", iApplicationThreadClass, Intent.class, String.class, iIntentReceiverClass, int.class, + String.class, Bundle.class, String[].class, int.class, Bundle.class, boolean.class, boolean.class, int.class); + return broadcastIntentMethod; + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + return broadcastIntentMethod; + } + private ContentProvider getContentProviderExternal(String name, IBinder token) { try { Method method = getGetContentProviderExternalMethod(); @@ -84,4 +103,13 @@ public class ActivityManager { public ContentProvider createSettingsProvider() { return getContentProviderExternal("settings", new Binder()); } + + public void sendBroadcast(Intent intent) { + try { + Method method = getBroadcastIntentMethod(); + method.invoke(manager, null, intent, null, null, 0, null, null, null, -1, null, true, false, ServiceManager.USER_ID); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { + Ln.e("Could not invoke method", e); + } + } }