Skip to content

Commit

Permalink
Adapt to display API changes
Browse files Browse the repository at this point in the history
The method SurfaceControl.createDisplay() has been removed in AOSP.

Use DisplayManager to create a VirtualDisplay object instead.

Fixes #4646 <#4646>
Fixes #4656 <#4656>
PR #4657 <#4657>

Signed-off-by: Romain Vimont <rom@rom1v.com>
  • Loading branch information
DerekWuYD authored and rom1v committed Feb 10, 2024
1 parent f7b4a18 commit be3f949
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 9 deletions.
4 changes: 4 additions & 0 deletions server/src/main/java/com/genymobile/scrcpy/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ public void dispatchPrimaryClipChanged() {
}
}

public int getDisplayId() {
return displayId;
}

public synchronized void setMaxSize(int newMaxSize) {
maxSize = newMaxSize;
screenInfo = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation);
Expand Down
29 changes: 26 additions & 3 deletions server/src/main/java/com/genymobile/scrcpy/ScreenCapture.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -34,9 +37,29 @@ public void start(Surface surface) {

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
Expand Down Expand Up @@ -69,7 +92,7 @@ public void onRotationChanged(int rotation) {
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
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;
Expand All @@ -16,6 +18,7 @@
@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 {
Expand Down Expand Up @@ -108,4 +111,17 @@ public int[] getDisplayIds() {
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,8 @@ public static void setDisplaySurface(IBinder displayToken, Surface surface) {
}
}

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 {
Expand Down

0 comments on commit be3f949

Please sign in to comment.