aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/invalid/lena/scrcpy/Mirror.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/invalid/lena/scrcpy/Mirror.java')
-rw-r--r--app/src/main/java/invalid/lena/scrcpy/Mirror.java63
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