The text input control_event was initially designed for mapping SDL_TextInputEvent, limited to 32 characters. For simplicity, the copy/paste feature was implemented using the same control_event: it just sends the text to paste. However, the pasted text might have a length breaking some assumptions: - on the client, the event max-size was smaller than the text max-length, - on the server, the raw buffer storing the events was smaller than the max event size. Fix these inconsistencies, and encode the length on 2 bytes, to accept more than 256 characters. Fixes <https://github.com/Genymobile/scrcpy/issues/10>.
173 lines
6.6 KiB
Java
173 lines
6.6 KiB
Java
package com.genymobile.scrcpy;
|
|
|
|
import android.view.KeyEvent;
|
|
import android.view.MotionEvent;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.DataOutputStream;
|
|
import java.io.IOException;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Arrays;
|
|
|
|
import org.junit.Assert;
|
|
import org.junit.Test;
|
|
|
|
public class ControlEventReaderTest {
|
|
|
|
@Test
|
|
public void testParseKeycodeEvent() throws IOException {
|
|
ControlEventReader reader = new ControlEventReader();
|
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
DataOutputStream dos = new DataOutputStream(bos);
|
|
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
|
dos.writeByte(KeyEvent.ACTION_UP);
|
|
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
|
byte[] packet = bos.toByteArray();
|
|
|
|
reader.readFrom(new ByteArrayInputStream(packet));
|
|
ControlEvent event = reader.next();
|
|
|
|
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
|
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
|
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
|
}
|
|
|
|
@Test
|
|
public void testParseTextEvent() throws IOException {
|
|
ControlEventReader reader = new ControlEventReader();
|
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
DataOutputStream dos = new DataOutputStream(bos);
|
|
dos.writeByte(ControlEvent.TYPE_TEXT);
|
|
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
|
dos.writeShort(text.length);
|
|
dos.write(text);
|
|
byte[] packet = bos.toByteArray();
|
|
|
|
reader.readFrom(new ByteArrayInputStream(packet));
|
|
ControlEvent event = reader.next();
|
|
|
|
Assert.assertEquals(ControlEvent.TYPE_TEXT, event.getType());
|
|
Assert.assertEquals("testé", event.getText());
|
|
}
|
|
|
|
@Test
|
|
public void testParseLongTextEvent() throws IOException {
|
|
ControlEventReader reader = new ControlEventReader();
|
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
DataOutputStream dos = new DataOutputStream(bos);
|
|
dos.writeByte(ControlEvent.TYPE_TEXT);
|
|
byte[] text = new byte[ControlEventReader.TEXT_MAX_LENGTH];
|
|
Arrays.fill(text, (byte) 'a');
|
|
dos.writeShort(text.length);
|
|
dos.write(text);
|
|
byte[] packet = bos.toByteArray();
|
|
|
|
reader.readFrom(new ByteArrayInputStream(packet));
|
|
ControlEvent event = reader.next();
|
|
|
|
Assert.assertEquals(ControlEvent.TYPE_TEXT, event.getType());
|
|
Assert.assertEquals(new String(text, StandardCharsets.US_ASCII), event.getText());
|
|
}
|
|
|
|
@Test
|
|
public void testParseMouseEvent() throws IOException {
|
|
ControlEventReader reader = new ControlEventReader();
|
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
DataOutputStream dos = new DataOutputStream(bos);
|
|
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
|
dos.writeByte(MotionEvent.ACTION_DOWN);
|
|
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
|
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
|
byte[] packet = bos.toByteArray();
|
|
|
|
reader.readFrom(new ByteArrayInputStream(packet));
|
|
ControlEvent event = reader.next();
|
|
|
|
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
|
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
|
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
|
}
|
|
|
|
@Test
|
|
public void testMultiEvents() throws IOException {
|
|
ControlEventReader reader = new ControlEventReader();
|
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
DataOutputStream dos = new DataOutputStream(bos);
|
|
|
|
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
|
dos.writeByte(KeyEvent.ACTION_UP);
|
|
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
|
|
|
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
|
dos.writeByte(MotionEvent.ACTION_DOWN);
|
|
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
|
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
|
|
|
byte[] packet = bos.toByteArray();
|
|
reader.readFrom(new ByteArrayInputStream(packet));
|
|
|
|
ControlEvent event = reader.next();
|
|
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
|
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
|
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
|
|
|
event = reader.next();
|
|
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
|
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
|
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
|
}
|
|
|
|
@Test
|
|
public void testPartialEvents() throws IOException {
|
|
ControlEventReader reader = new ControlEventReader();
|
|
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
DataOutputStream dos = new DataOutputStream(bos);
|
|
|
|
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
|
dos.writeByte(KeyEvent.ACTION_UP);
|
|
dos.writeInt(KeyEvent.KEYCODE_ENTER);
|
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
|
|
|
dos.writeByte(ControlEvent.TYPE_KEYCODE);
|
|
dos.writeByte(MotionEvent.ACTION_DOWN);
|
|
|
|
byte[] packet = bos.toByteArray();
|
|
reader.readFrom(new ByteArrayInputStream(packet));
|
|
|
|
ControlEvent event = reader.next();
|
|
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
|
Assert.assertEquals(KeyEvent.ACTION_UP, event.getAction());
|
|
Assert.assertEquals(KeyEvent.KEYCODE_ENTER, event.getKeycode());
|
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
|
|
|
event = reader.next();
|
|
Assert.assertNull(event); // the event is not complete
|
|
|
|
bos.reset();
|
|
dos.writeInt(MotionEvent.BUTTON_PRIMARY);
|
|
dos.writeInt(KeyEvent.META_CTRL_ON);
|
|
packet = bos.toByteArray();
|
|
reader.readFrom(new ByteArrayInputStream(packet));
|
|
|
|
// the event is now complete
|
|
event = reader.next();
|
|
Assert.assertEquals(ControlEvent.TYPE_KEYCODE, event.getType());
|
|
Assert.assertEquals(MotionEvent.ACTION_DOWN, event.getAction());
|
|
Assert.assertEquals(MotionEvent.BUTTON_PRIMARY, event.getKeycode());
|
|
Assert.assertEquals(KeyEvent.META_CTRL_ON, event.getMetaState());
|
|
}
|
|
}
|