aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/invalid/lena/scrcpy/ControlMessages.java')
-rw-r--r--app/src/main/java/invalid/lena/scrcpy/ControlMessages.java37
1 files changed, 34 insertions, 3 deletions
diff --git a/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java b/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java
index aba2ca8..6455a65 100644
--- a/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java
+++ b/app/src/main/java/invalid/lena/scrcpy/ControlMessages.java
@@ -8,28 +8,52 @@ import java.nio.charset.StandardCharsets;
// unit-tested without android.* on the classpath.
public final class ControlMessages {
- static final int MAX_CLIPBOARD_BYTES = 1 << 20;
+ // scrcpy caps a whole control message at MESSAGE_MAX_SIZE = 256 KiB.
+ // For SET_CLIPBOARD that leaves 256 KiB minus the 14-byte header
+ // (type 1, sequence 8, paste flag 1, length 4); see the server's
+ // ControlMessageReader.CLIPBOARD_TEXT_MAX_LENGTH. Going over makes
+ // the server raise ControlProtocolException and drop the control
+ // connection, taking the session with it, so refuse locally instead.
+ static final int MAX_CLIPBOARD_BYTES = (1 << 18) - 14;
+
+ // The reverse direction, from the server's DeviceMessageWriter:
+ // 256 KiB minus its 5-byte header (type 1, length 4). Used to bound
+ // what we are willing to read off the control socket.
+ static final int MAX_DEVICE_CLIPBOARD_BYTES = (1 << 18) - 5;
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;
+ public static final int TYPE_RESET_VIDEO = 17;
// 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;
+ // AOSP keycodes, mirrored rather than imported so this stays
+ // android-free. KeyEvent.KEYCODE_HOME / KEYCODE_APP_SWITCH.
+ public static final int KEYCODE_HOME = 3;
+ public static final int KEYCODE_APP_SWITCH = 187;
+
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) {
+ if (targetW < 1 || targetW > 0xffff || targetH < 1 || targetH > 0xffff) {
+ throw new IllegalArgumentException("touch target size is out of range");
+ }
+ if (x < 0 || x >= targetW || y < 0 || y >= targetH) {
+ throw new IllegalArgumentException("touch position is out of range");
+ }
+ if (pressureU16 < 0 || pressureU16 > 0xffff) {
+ throw new IllegalArgumentException("touch pressure is out of range");
+ }
byte[] m = new byte[TOUCH_MSG_LEN];
m[0] = TYPE_INJECT_TOUCH_EVENT;
m[1] = (byte) action;
@@ -61,7 +85,14 @@ public final class ControlMessages {
return new byte[]{(byte) TYPE_BACK_OR_SCREEN_ON, (byte) action};
}
+ public static byte[] resetVideo() {
+ return new byte[]{(byte) TYPE_RESET_VIDEO};
+ }
+
public static byte[] setClipboard(long sequence, boolean paste, String text) {
+ // UTF-8 is at least one byte per char, so this rejects the
+ // hopeless cases without encoding a huge string first. The byte
+ // count below is the check that actually matters.
if (text.length() > MAX_CLIPBOARD_BYTES) {
throw new IllegalArgumentException("clipboard text is too large");
}