diff options
Diffstat (limited to 'app/src/main/java/invalid/lena/scrcpy/Mirror.java')
| -rw-r--r-- | app/src/main/java/invalid/lena/scrcpy/Mirror.java | 63 |
1 files changed, 56 insertions, 7 deletions
diff --git a/app/src/main/java/invalid/lena/scrcpy/Mirror.java b/app/src/main/java/invalid/lena/scrcpy/Mirror.java index 2c361da..2a9d390 100644 --- a/app/src/main/java/invalid/lena/scrcpy/Mirror.java +++ b/app/src/main/java/invalid/lena/scrcpy/Mirror.java @@ -60,6 +60,10 @@ public final class Mirror extends Activity { private Devices.Device target; private Session session; private Surface currentSurface; + private boolean ownsCurrentSurface; + private volatile boolean destroyed; + private long sessionGeneration; + private boolean stoppingSession; private State state = State.CONNECTING; private int connectedW, connectedH; @@ -138,6 +142,7 @@ public final class Mirror extends Activity { try { Adb a = Adb.getInstance(this); runOnUiThread(() -> { + if (destroyed) return; adb = a; if (session == null && currentSurface != null) { startSession(currentSurface); @@ -146,6 +151,7 @@ public final class Mirror extends Activity { } catch (Exception e) { Log.e(e, "mirror: adb init"); runOnUiThread(() -> { + if (destroyed) return; Toast.makeText(this, "adb init: " + e.getMessage(), Toast.LENGTH_LONG).show(); finish(); @@ -161,7 +167,7 @@ public final class Mirror extends Activity { @Override public void onSurfaceTextureAvailable(SurfaceTexture st, int w, int h) { Log.i("mirror: texture available %dx%d", w, h); - attachSurface(new Surface(st), w, h); + attachSurface(new Surface(st), true, w, h); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture st, int w, int h) { @@ -188,7 +194,7 @@ public final class Mirror extends Activity { @Override public void surfaceCreated(SurfaceHolder holder) { Log.i("mirror: surface created"); - attachSurface(holder.getSurface(), 0, 0); + attachSurface(holder.getSurface(), false, 0, 0); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { @@ -204,30 +210,43 @@ public final class Mirror extends Activity { // ---- session driver ---- - private void attachSurface(Surface s, int w, int h) { + private void attachSurface(Surface s, boolean owned, int w, int h) { + if (session != null && currentSurface != null) session.swapSurface(null); + releaseOwnedSurface(); currentSurface = s; + ownsCurrentSurface = owned; if (session != null) { session.swapSurface(s); if (w > 0) session.setViewSize(w, h); return; } if (adb == null) return; // adb-init thread will start the session + if (stoppingSession) return; // stop worker starts the latest target if (state == State.DISCONNECTED) return; // wait for user to tap reconnect startSession(s); if (w > 0) session.setViewSize(w, h); } private void detachSurface() { - currentSurface = null; if (session != null) session.swapSurface(null); + releaseOwnedSurface(); + currentSurface = null; + } + + private void releaseOwnedSurface() { + if (ownsCurrentSurface && currentSurface != null) currentSurface.release(); + ownsCurrentSurface = false; } private void startSession(Surface s) { + if (destroyed) return; state = State.CONNECTING; updateStatusBar(); + long generation = ++sessionGeneration; session = new Session(this, adb, target, s, new Session.Listener() { @Override public void onConnected(int w, int h) { runOnUiThread(() -> { + if (destroyed || generation != sessionGeneration) return; state = State.CONNECTED; connectedW = w; connectedH = h; updateStatusBar(); @@ -236,12 +255,14 @@ public final class Mirror extends Activity { @Override public void onReconnecting() { Log.i("mirror: link lost, reconnecting"); runOnUiThread(() -> { + if (destroyed || generation != sessionGeneration) return; state = State.CONNECTING; updateStatusBar(); }); } @Override public void onError(Throwable t) { runOnUiThread(() -> { + if (destroyed || generation != sessionGeneration) return; Toast.makeText(Mirror.this, "session error: " + t.getMessage(), Toast.LENGTH_LONG).show(); }); @@ -249,6 +270,7 @@ public final class Mirror extends Activity { @Override public void onStopped() { Log.i("mirror: session stopped"); runOnUiThread(() -> { + if (destroyed || generation != sessionGeneration) return; state = State.DISCONNECTED; updateStatusBar(); }); @@ -286,10 +308,13 @@ public final class Mirror extends Activity { private void reconnect() { Log.i("mirror: reconnect tapped"); - Session old = session; - session = null; state = State.CONNECTING; updateStatusBar(); + if (stoppingSession) return; + stoppingSession = true; + Session old = session; + session = null; + sessionGeneration++; // Stop the old session off the UI thread (teardown closes // sockets and joins the server's log pump), THEN start the new // one. Sequencing matters: both sessions share the singleton @@ -298,6 +323,8 @@ public final class Mirror extends Activity { new Thread(() -> { if (old != null) old.stop(); runOnUiThread(() -> { + if (destroyed) return; + stoppingSession = false; if (session != null) return; // another path already started one if (adb == null || currentSurface == null) return; startSession(currentSurface); @@ -305,6 +332,24 @@ public final class Mirror extends Activity { }, "session-stop").start(); } + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + String host = intent.getStringExtra(EXTRA_HOST); + int port = intent.getIntExtra(EXTRA_PORT, -1); + if (host == null || port <= 0 || port > 65535) { + Log.w("mirror: ignoring bad replacement target host=%s port=%d", host, port); + return; + } + if (target.host.equals(host) && target.port == port) return; + + setIntent(intent); + target = new Devices.Device(host, port); + connectedW = connectedH = 0; + if (overlayTarget != null) overlayTarget.setText("target: " + target); + reconnect(); + } + private void updateStatusBar() { if (statusText == null) return; String s; @@ -394,8 +439,11 @@ public final class Mirror extends Activity { @Override protected void onDestroy() { - super.onDestroy(); + destroyed = true; + sessionGeneration++; ui.removeCallbacksAndMessages(null); + releaseOwnedSurface(); + currentSurface = null; Session s = session; session = null; if (s != null) { @@ -404,6 +452,7 @@ public final class Mirror extends Activity { new Thread(s::stop, "session-stop").start(); } stopService(new Intent(this, Sessions.class)); + super.onDestroy(); } // Android 13+ requires runtime grant for POST_NOTIFICATIONS. The |