mirror of https://github.com/Genymobile/scrcpy
Adapt to display API changes
The method SurfaceControl.createDisplay() has been removed in AOSP. Use DisplayManager to create a VirtualDisplay object instead. Fixes #4646 <https://github.com/Genymobile/scrcpy/issues/4646> Fixes #4656 <https://github.com/Genymobile/scrcpy/issues/4656> PR #4657 <https://github.com/Genymobile/scrcpy/pull/4657> Signed-off-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
parent
f7b4a18b43
commit
be3f949aa5
|
@ -164,6 +164,10 @@ public final class Device {
|
|||
}
|
||||
}
|
||||
|
||||
public int getDisplayId() {
|
||||
return displayId;
|
||||
}
|
||||
|
||||
public synchronized void setMaxSize(int newMaxSize) {
|
||||
maxSize = newMaxSize;
|
||||
screenInfo = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package com.genymobile.scrcpy;
|
||||
|
||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||
import com.genymobile.scrcpy.wrappers.SurfaceControl;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.display.VirtualDisplay;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.view.Surface;
|
||||
|
@ -11,6 +13,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
|||
|
||||
private final Device device;
|
||||
private IBinder display;
|
||||
private VirtualDisplay virtualDisplay;
|
||||
|
||||
public ScreenCapture(Device device) {
|
||||
this.device = device;
|
||||
|
@ -34,9 +37,29 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
|||
|
||||
if (display != null) {
|
||||
SurfaceControl.destroyDisplay(display);
|
||||
display = null;
|
||||
}
|
||||
if (virtualDisplay != null) {
|
||||
virtualDisplay.release();
|
||||
virtualDisplay = null;
|
||||
}
|
||||
|
||||
try {
|
||||
display = createDisplay();
|
||||
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack);
|
||||
Ln.d("Display: using SurfaceControl API");
|
||||
} catch (Exception surfaceControlException) {
|
||||
Rect videoRect = screenInfo.getVideoSize().toRect();
|
||||
try {
|
||||
virtualDisplay = ServiceManager.getDisplayManager()
|
||||
.createVirtualDisplay("scrcpy", videoRect.width(), videoRect.height(), device.getDisplayId(), surface);
|
||||
Ln.d("Display: using DisplayManager API");
|
||||
} catch (Exception displayManagerException) {
|
||||
Ln.e("Could not create display using SurfaceControl", surfaceControlException);
|
||||
Ln.e("Could not create display using DisplayManager", displayManagerException);
|
||||
throw new AssertionError("Could not create display");
|
||||
}
|
||||
}
|
||||
display = createDisplay();
|
||||
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,7 +92,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
|||
requestReset();
|
||||
}
|
||||
|
||||
private static IBinder createDisplay() {
|
||||
private static IBinder createDisplay() throws Exception {
|
||||
// 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".
|
||||
boolean secure = Build.VERSION.SDK_INT < Build.VERSION_CODES.R || (Build.VERSION.SDK_INT == Build.VERSION_CODES.R && !"S".equals(
|
||||
|
|
|
@ -6,7 +6,9 @@ import com.genymobile.scrcpy.Ln;
|
|||
import com.genymobile.scrcpy.Size;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.hardware.display.VirtualDisplay;
|
||||
import android.view.Display;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
@ -16,6 +18,7 @@ import java.util.regex.Pattern;
|
|||
@SuppressLint("PrivateApi,DiscouragedPrivateApi")
|
||||
public final class DisplayManager {
|
||||
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
|
||||
private Method createVirtualDisplayMethod;
|
||||
|
||||
static DisplayManager create() {
|
||||
try {
|
||||
|
@ -108,4 +111,17 @@ public final class DisplayManager {
|
|||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Method getCreateVirtualDisplayMethod() throws NoSuchMethodException {
|
||||
if (createVirtualDisplayMethod == null) {
|
||||
createVirtualDisplayMethod = android.hardware.display.DisplayManager.class
|
||||
.getMethod("createVirtualDisplay", String.class, int.class, int.class, int.class, Surface.class);
|
||||
}
|
||||
return createVirtualDisplayMethod;
|
||||
}
|
||||
|
||||
public VirtualDisplay createVirtualDisplay(String name, int width, int height, int displayIdToMirror, Surface surface) throws Exception {
|
||||
Method method = getCreateVirtualDisplayMethod();
|
||||
return (VirtualDisplay) method.invoke(null, name, width, height, displayIdToMirror, surface);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,12 +77,8 @@ public final class SurfaceControl {
|
|||
}
|
||||
}
|
||||
|
||||
public static IBinder createDisplay(String name, boolean secure) {
|
||||
try {
|
||||
return (IBinder) CLASS.getMethod("createDisplay", String.class, boolean.class).invoke(null, name, secure);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
public static IBinder createDisplay(String name, boolean secure) throws Exception {
|
||||
return (IBinder) CLASS.getMethod("createDisplay", String.class, boolean.class).invoke(null, name, secure);
|
||||
}
|
||||
|
||||
private static Method getGetBuiltInDisplayMethod() throws NoSuchMethodException {
|
||||
|
|
Loading…
Reference in New Issue