Restart capture when screen resolution changes
This commit is contained in:
parent
762ed2755a
commit
391f2de3fa
@ -2,6 +2,7 @@ package com.genymobile.scrcpy;
|
||||
|
||||
import com.genymobile.scrcpy.wrappers.ClipboardManager;
|
||||
import com.genymobile.scrcpy.wrappers.DisplayControl;
|
||||
import com.genymobile.scrcpy.wrappers.DisplayManager;
|
||||
import com.genymobile.scrcpy.wrappers.InputManager;
|
||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||
import com.genymobile.scrcpy.wrappers.SurfaceControl;
|
||||
@ -10,6 +11,8 @@ import com.genymobile.scrcpy.wrappers.WindowManager;
|
||||
import android.content.IOnPrimaryClipChangedListener;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.SystemClock;
|
||||
import android.view.IDisplayFoldListener;
|
||||
@ -33,6 +36,10 @@ public final class Device {
|
||||
public static final int LOCK_VIDEO_ORIENTATION_UNLOCKED = -1;
|
||||
public static final int LOCK_VIDEO_ORIENTATION_INITIAL = -2;
|
||||
|
||||
public interface DisplayChangeListener {
|
||||
void onDisplayChanged();
|
||||
}
|
||||
|
||||
public interface RotationListener {
|
||||
void onRotationChanged(int rotation);
|
||||
}
|
||||
@ -51,6 +58,7 @@ public final class Device {
|
||||
|
||||
private Size deviceSize;
|
||||
private ScreenInfo screenInfo;
|
||||
private DisplayChangeListener displayChangeListener;
|
||||
private RotationListener rotationListener;
|
||||
private FoldListener foldListener;
|
||||
private ClipboardListener clipboardListener;
|
||||
@ -86,6 +94,27 @@ public final class Device {
|
||||
screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation);
|
||||
layerStack = displayInfo.getLayerStack();
|
||||
|
||||
HandlerThread displayListenerThread = new HandlerThread("DisplayListenerThread");
|
||||
displayListenerThread.start();
|
||||
|
||||
Handler displayListenerHandler = new Handler(displayListenerThread.getLooper());
|
||||
ServiceManager.getDisplayManager().registerDisplayListener(new DisplayManager.DisplayListener() {
|
||||
@Override
|
||||
public void onDisplayChanged(int displayId) {
|
||||
if (Device.this.displayId != displayId) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(displayId);
|
||||
deviceSize = displayInfo.getSize();
|
||||
screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation);
|
||||
|
||||
if (displayChangeListener != null) {
|
||||
displayChangeListener.onDisplayChanged();
|
||||
}
|
||||
}
|
||||
}, displayListenerHandler);
|
||||
|
||||
ServiceManager.getWindowManager().registerRotationWatcher(new IRotationWatcher.Stub() {
|
||||
@Override
|
||||
public void onRotationChanged(int rotation) {
|
||||
@ -253,6 +282,10 @@ public final class Device {
|
||||
return ServiceManager.getPowerManager().isScreenOn();
|
||||
}
|
||||
|
||||
public synchronized void setDisplayChangeListener(DisplayChangeListener displayChangeListener) {
|
||||
this.displayChangeListener = displayChangeListener;
|
||||
}
|
||||
|
||||
public synchronized void setRotationListener(RotationListener rotationListener) {
|
||||
this.rotationListener = rotationListener;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.view.Surface;
|
||||
|
||||
public class ScreenCapture extends SurfaceCapture implements Device.RotationListener, Device.FoldListener {
|
||||
public class ScreenCapture extends SurfaceCapture implements Device.DisplayChangeListener, Device.RotationListener, Device.FoldListener {
|
||||
|
||||
private final Device device;
|
||||
private IBinder display;
|
||||
@ -18,6 +18,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
device.setDisplayChangeListener(this);
|
||||
device.setRotationListener(this);
|
||||
device.setFoldListener(this);
|
||||
}
|
||||
@ -41,6 +42,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
device.setDisplayChangeListener(null);
|
||||
device.setRotationListener(null);
|
||||
device.setFoldListener(null);
|
||||
if (display != null) {
|
||||
@ -69,6 +71,11 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
||||
requestReset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayChanged() {
|
||||
requestReset();
|
||||
}
|
||||
|
||||
private static IBinder createDisplay() {
|
||||
// Since Android 12 (preview), secure displays could not be created with shell permissions anymore.
|
||||
// On Android 12 preview, SDK_INT is still R (not S), but CODENAME is "S".
|
||||
|
@ -5,13 +5,20 @@ import com.genymobile.scrcpy.DisplayInfo;
|
||||
import com.genymobile.scrcpy.Ln;
|
||||
import com.genymobile.scrcpy.Size;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.view.Display;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class DisplayManager {
|
||||
|
||||
// Constant copied from AOSP framework_base: core/java/android/hardware/display/DisplayManager.java
|
||||
private static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;
|
||||
|
||||
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
|
||||
|
||||
public DisplayManager(Object manager) {
|
||||
@ -94,4 +101,47 @@ public final class DisplayManager {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerDisplayListener(DisplayListener listener, Handler handler) {
|
||||
try {
|
||||
Class<?> displayListenerClass = Class.forName("android.hardware.display.DisplayManager$DisplayListener");
|
||||
Object displayListenerProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
|
||||
new Class[]{displayListenerClass},
|
||||
(proxy, method, args) -> {
|
||||
if ("onDisplayChanged".equals(method.getName())) {
|
||||
listener.onDisplayChanged((int) args[0]);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
try {
|
||||
manager.getClass()
|
||||
.getMethod("registerDisplayListener", displayListenerClass, Handler.class, long.class)
|
||||
.invoke(manager, displayListenerProxy, handler, EVENT_FLAG_DISPLAY_CHANGED);
|
||||
return;
|
||||
} catch (NoSuchMethodException e) {
|
||||
// fall-through
|
||||
}
|
||||
}
|
||||
|
||||
manager.getClass()
|
||||
.getMethod("registerDisplayListener", displayListenerClass, Handler.class)
|
||||
.invoke(manager, displayListenerProxy, handler);
|
||||
} catch (Exception e) {
|
||||
// Screen size won't be updated, not a fatal error
|
||||
Ln.e("Could not register display listener", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Partially copied from AOSP framework_base: core/java/android/hardware/display/DisplayManager.java
|
||||
public interface DisplayListener {
|
||||
/**
|
||||
* Called whenever the properties of a logical {@link android.view.Display},
|
||||
* such as size and density, have changed.
|
||||
*
|
||||
* @param displayId The id of the logical display that changed.
|
||||
*/
|
||||
void onDisplayChanged(int displayId);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user