From eb0c8951196c637e44daf3c0617b131b997d5d2c Mon Sep 17 00:00:00 2001 From: Lena Date: Thu, 1 Jan 2026 00:00:00 +0000 Subject: scrcpy-android: mirror an Android device over wireless ADB 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. --- .../test/java/invalid/lena/scrcpy/WireTest.java | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 app/src/test/java/invalid/lena/scrcpy/WireTest.java (limited to 'app/src/test/java/invalid/lena/scrcpy/WireTest.java') diff --git a/app/src/test/java/invalid/lena/scrcpy/WireTest.java b/app/src/test/java/invalid/lena/scrcpy/WireTest.java new file mode 100644 index 0000000..9cee6c5 --- /dev/null +++ b/app/src/test/java/invalid/lena/scrcpy/WireTest.java @@ -0,0 +1,94 @@ +package invalid.lena.scrcpy; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.EOFException; + +public class WireTest { + + @Test + public void be32RoundTrip() { + byte[] b = new byte[4]; + int[] cases = {0, 1, -1, 0x7fffffff, 0x80000000, 0x12345678}; + for (int v : cases) { + Wire.writeBe32(b, 0, v); + assertEquals(v, Wire.readBe32(b, 0)); + } + } + + @Test + public void be32Layout() { + byte[] b = new byte[4]; + Wire.writeBe32(b, 0, 0x12345678); + assertArrayEquals(new byte[]{0x12, 0x34, 0x56, 0x78}, b); + } + + @Test + public void be64RoundTrip() { + byte[] b = new byte[8]; + long[] cases = {0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE, 0x0123456789abcdefL}; + for (long v : cases) { + Wire.writeBe64(b, 0, v); + assertEquals(v, Wire.readBe64(b, 0)); + } + } + + @Test + public void le32RoundTrip() { + byte[] b = new byte[4]; + int[] cases = {0, 1, -1, 0x7fffffff, 0x80000000, 0x12345678}; + for (int v : cases) { + Wire.writeLe32(b, 0, v); + assertEquals(v, Wire.readLe32(b, 0)); + } + } + + @Test + public void le32Layout() { + byte[] b = new byte[4]; + Wire.writeLe32(b, 0, 0x12345678); + assertArrayEquals(new byte[]{0x78, 0x56, 0x34, 0x12}, b); + } + + @Test + public void readFullyShortStreamThrows() throws Exception { + ByteArrayInputStream in = new ByteArrayInputStream(new byte[3]); + byte[] buf = new byte[8]; + try { + Wire.readFully(in, buf); + fail("expected EOFException"); + } catch (EOFException ignored) { + // expected + } + } + + @Test + public void fourccConstantsMatchScrcpy() { + // Big-endian uint32 of the 4-char ASCII tag, NUL-padded on the LEFT + // for short names (raw, aac) - mirrors AudioCodec / VideoCodec. + assertEquals(0x68_32_36_34, Wire.CODEC_H264); // "h264" + assertEquals(0x68_32_36_35, Wire.CODEC_H265); // "h265" + assertEquals(0x61_76_30_31, Wire.CODEC_AV1); // "av01" + assertEquals(0x6f_70_75_73, Wire.CODEC_OPUS); // "opus" + assertEquals(0x66_6c_61_63, Wire.CODEC_FLAC); // "flac" + assertEquals(0x00_61_61_63, Wire.CODEC_AAC); // "\0aac" + assertEquals(0x00_72_61_77, Wire.CODEC_RAW); // "\0raw" + } + + @Test + public void fourccName() { + assertEquals("h264", Wire.fourccName(Wire.CODEC_H264)); + assertEquals("opus", Wire.fourccName(Wire.CODEC_OPUS)); + } + + @Test + public void fourccNameTrimsLeadingNuls() { + assertEquals("raw", Wire.fourccName(Wire.CODEC_RAW)); + assertEquals("aac", Wire.fourccName(Wire.CODEC_AAC)); + } +} -- cgit v1.2.3