mirror of
https://github.com/Genymobile/scrcpy
synced 2025-08-30 13:58:08 +00:00
Run a main looper
Instead of blocking the main thread until completion, run a looper. This will allow the main thread to process any event posted to the main looper. Refs #6009 comment <https://github.com/Genymobile/scrcpy/pull/6009#issuecomment-2940810736> PR #6129 <https://github.com/Genymobile/scrcpy/pull/6129>
This commit is contained in:
@@ -25,9 +25,11 @@ import com.genymobile.scrcpy.video.SurfaceEncoder;
|
||||
import com.genymobile.scrcpy.video.VideoSource;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -55,17 +57,7 @@ public final class Server {
|
||||
this.fatalError = true;
|
||||
}
|
||||
if (running == 0 || this.fatalError) {
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void await() {
|
||||
try {
|
||||
while (running > 0 && !fatalError) {
|
||||
wait();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
Looper.getMainLooper().quitSafely();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,6 +96,7 @@ public final class Server {
|
||||
boolean audio = options.getAudio();
|
||||
boolean sendDummyByte = options.getSendDummyByte();
|
||||
|
||||
prepareMainLooper();
|
||||
Workarounds.apply();
|
||||
|
||||
List<AsyncProcessor> asyncProcessors = new ArrayList<>();
|
||||
@@ -172,7 +165,7 @@ public final class Server {
|
||||
});
|
||||
}
|
||||
|
||||
completion.await();
|
||||
Looper.loop(); // interrupted by the Completion implementation
|
||||
} finally {
|
||||
if (cleanUp != null) {
|
||||
cleanUp.interrupt();
|
||||
@@ -201,6 +194,20 @@ public final class Server {
|
||||
}
|
||||
}
|
||||
|
||||
private static void prepareMainLooper() {
|
||||
// Like Looper.prepareMainLooper(), but with quitAllowed set to true
|
||||
Looper.prepare();
|
||||
synchronized (Looper.class) {
|
||||
try {
|
||||
Field field = Looper.class.getDeclaredField("sMainLooper");
|
||||
field.setAccessible(true);
|
||||
field.set(null, Looper.myLooper());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
int status = 0;
|
||||
try {
|
||||
|
@@ -29,8 +29,6 @@ public final class Workarounds {
|
||||
private static final Object ACTIVITY_THREAD;
|
||||
|
||||
static {
|
||||
prepareMainLooper();
|
||||
|
||||
try {
|
||||
// ActivityThread activityThread = new ActivityThread();
|
||||
ACTIVITY_THREAD_CLASS = Class.forName("android.app.ActivityThread");
|
||||
@@ -77,19 +75,6 @@ public final class Workarounds {
|
||||
fillAppContext();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static void prepareMainLooper() {
|
||||
// Some devices internally create a Handler when creating an input Surface, causing an exception:
|
||||
// "Can't create handler inside thread that has not called Looper.prepare()"
|
||||
// <https://github.com/Genymobile/scrcpy/issues/240>
|
||||
//
|
||||
// Use Looper.prepareMainLooper() instead of Looper.prepare() to avoid a NullPointerException:
|
||||
// "Attempt to read from field 'android.os.MessageQueue android.os.Looper.mQueue'
|
||||
// on a null object reference"
|
||||
// <https://github.com/Genymobile/scrcpy/issues/921>
|
||||
Looper.prepareMainLooper();
|
||||
}
|
||||
|
||||
private static void fillAppInfo() {
|
||||
try {
|
||||
// ActivityThread.AppBindData appBindData = new ActivityThread.AppBindData();
|
||||
|
Reference in New Issue
Block a user