diff options
| author | Lena <lena@omega> | 2026-01-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-06-24 22:14:50 +0300 |
| commit | eb0c8951196c637e44daf3c0617b131b997d5d2c (patch) | |
| tree | 2f83b6a41cee745467e53fc401942b82cea286ea /app/src/main/java/invalid/lena/scrcpy/ControlMessages.java | |
| download | scrcpy-android-0.1.tar.gz | |
scrcpy-android: mirror an Android device over wireless ADB0.1
Native Java app for Android 12+ that mirrors another Android
device over wireless ADB, forwarding video, audio, touch input,
and clipboard. Bundles a pinned scrcpy-server.jar and the
vendored libadb-android stack. Supports h264/h265/av1 video and
raw/opus audio with in-app codec selection. No NDK, no Kotlin.
Includes JVM unit tests and a Docker-based emulator e2e rig.
Diffstat (limited to 'app/src/main/java/invalid/lena/scrcpy/ControlMessages.java')
| -rw-r--r-- | app/src/main/java/invalid/lena/scrcpy/ControlMessages.java | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java b/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java new file mode 100644 index 0000000..bd983ed --- /dev/null +++ b/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java @@ -0,0 +1,72 @@ +package invalid.lena.scrcpy; + +import java.nio.charset.StandardCharsets; + +// Pure-java encoders for scrcpy control messages. Layouts mirror +// com.genymobile.scrcpy.control.ControlMessageReader in the scrcpy +// server source. Extracted from Controller so the wire format can be +// unit-tested without android.* on the classpath. +public final class ControlMessages { + + public static final int TYPE_INJECT_KEYCODE = 0; + public static final int TYPE_INJECT_TEXT = 1; + public static final int TYPE_INJECT_TOUCH_EVENT = 2; + public static final int TYPE_BACK_OR_SCREEN_ON = 4; + public static final int TYPE_SET_CLIPBOARD = 9; + + // KeyEvent.ACTION_DOWN / ACTION_UP. Mirror the int values rather + // than depend on android.view.KeyEvent so this stays android-free. + public static final int ACTION_DOWN = 0; + public static final int ACTION_UP = 1; + + public static final int TOUCH_MSG_LEN = 32; // 1 + 1 + 8 + 4 + 4 + 2 + 2 + 2 + 4 + 4 + public static final int KEY_MSG_LEN = 14; // 1 + 1 + 4 + 4 + 4 + public static final int BACK_MSG_LEN = 2; // 1 + 1 + + private ControlMessages() {} + + public static byte[] touch(int action, long pointerId, + int x, int y, int targetW, int targetH, + int pressureU16, int actionButton, int buttons) { + byte[] m = new byte[TOUCH_MSG_LEN]; + m[0] = TYPE_INJECT_TOUCH_EVENT; + m[1] = (byte) action; + Wire.writeBe64(m, 2, pointerId); + Wire.writeBe32(m, 10, x); + Wire.writeBe32(m, 14, y); + m[18] = (byte)(targetW >>> 8); m[19] = (byte) targetW; + m[20] = (byte)(targetH >>> 8); m[21] = (byte) targetH; + m[22] = (byte)(pressureU16 >>> 8); m[23] = (byte) pressureU16; + Wire.writeBe32(m, 24, actionButton); + Wire.writeBe32(m, 28, buttons); + return m; + } + + public static byte[] keycode(int action, int keycode, int repeat, int metaState) { + byte[] m = new byte[KEY_MSG_LEN]; + m[0] = TYPE_INJECT_KEYCODE; + m[1] = (byte) action; + Wire.writeBe32(m, 2, keycode); + Wire.writeBe32(m, 6, repeat); + Wire.writeBe32(m, 10, metaState); + return m; + } + + // Single button-press event. scrcpy server interprets this as Back + // when the screen is on, or screen-on when it's off. We send a + // DOWN+UP pair to make a tap; this helper builds one byte pair. + public static byte[] backOrScreenOn(int action) { + return new byte[]{(byte) TYPE_BACK_OR_SCREEN_ON, (byte) action}; + } + + public static byte[] setClipboard(long sequence, boolean paste, String text) { + byte[] data = text.getBytes(StandardCharsets.UTF_8); + byte[] m = new byte[1 + 8 + 1 + 4 + data.length]; + m[0] = TYPE_SET_CLIPBOARD; + Wire.writeBe64(m, 1, sequence); + m[9] = (byte)(paste ? 1 : 0); + Wire.writeBe32(m, 10, data.length); + System.arraycopy(data, 0, m, 14, data.length); + return m; + } +} |