From ff7acf898b48359275a5b09b82ed926a945233f8 Mon Sep 17 00:00:00 2001 From: Lena Date: Wed, 1 Jul 2026 00:00:00 +0000 Subject: app: fix session lifecycle, teardown, and opus playback Opus playback never worked: feed() called dequeueInputBuffer() on a codec in async-callback mode, which always throws, so every packet was silently dropped. Feed input through the async callback with a bounded pending queue instead. Make bring-up transactional: roll back partially opened streams and the server shell on failure, join reader threads on stop, and close the owning ADB streams before releasing sinks. Replace the openAbstract watchdog thread with a real timeout in the vendored AdbConnection.open(), which also removes the half-open stream from the lookup table on failure. Harden the activity: release owned Surfaces, gate callbacks on a destroyed flag and a session generation, serialize reconnect, and handle target replacement via singleTask + onNewIntent. Propagate device-list write failures instead of swallowing them, bound the clipboard payload and the video pending queue against hostile peers, and discard incomplete recordings instead of keeping corrupt files. Use the mediaPlayback foreground-service type; Android 15 stops dataSync services after six hours. Drop the unused ACCESS_NETWORK_STATE permission. --- .../test/java/invalid/lena/scrcpy/ControlMessagesTest.java | 6 ++++++ .../test/java/invalid/lena/scrcpy/ControlStreamTest.java | 14 ++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'app/src/test/java/invalid/lena/scrcpy') diff --git a/app/src/test/java/invalid/lena/scrcpy/ControlMessagesTest.java b/app/src/test/java/invalid/lena/scrcpy/ControlMessagesTest.java index a84e18e..1890860 100644 --- a/app/src/test/java/invalid/lena/scrcpy/ControlMessagesTest.java +++ b/app/src/test/java/invalid/lena/scrcpy/ControlMessagesTest.java @@ -9,6 +9,12 @@ import java.nio.charset.StandardCharsets; public class ControlMessagesTest { + @Test(expected = IllegalArgumentException.class) + public void clipboardRejectsOversizedText() { + char[] chars = new char[ControlMessages.MAX_CLIPBOARD_BYTES + 1]; + ControlMessages.setClipboard(0, false, new String(chars)); + } + @Test public void touchByteLayout() { // ACTION_DOWN=0, single finger, target 1080x2400, x=100, y=200, full pressure diff --git a/app/src/test/java/invalid/lena/scrcpy/ControlStreamTest.java b/app/src/test/java/invalid/lena/scrcpy/ControlStreamTest.java index cafff81..8573d3b 100644 --- a/app/src/test/java/invalid/lena/scrcpy/ControlStreamTest.java +++ b/app/src/test/java/invalid/lena/scrcpy/ControlStreamTest.java @@ -7,6 +7,7 @@ import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.util.concurrent.atomic.AtomicBoolean; import java.io.DataOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -149,4 +150,17 @@ public class ControlStreamTest { System.arraycopy(bytes, bytes.length - 14, tail, 0, 14); for (int i = 0; i < 14; i++) assertEquals(key[i], tail[i]); } + + @Test + public void nonDroppableOverflowFailsStream() { + AtomicBoolean failed = new AtomicBoolean(); + ControlStream cs = new ControlStream( + new ByteArrayInputStream(new byte[0]), new ByteArrayOutputStream(), + () -> failed.set(true)); + + byte[] key = ControlMessages.keycode(0, 29, 0, 0); + for (int i = 0; i < 257; i++) cs.send(key); + + assertEquals(true, failed.get()); + } } -- cgit v1.2.3