Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the VirtualDisplay method to fix the SurfaceControl API changes. #4657

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions server/src/main/java/com/genymobile/scrcpy/ScreenCapture.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.genymobile.scrcpy;

import com.genymobile.scrcpy.wrappers.DisplayManager;
import com.genymobile.scrcpy.wrappers.SurfaceControl;
import com.genymobile.scrcpy.wrappers.MediaProjectionGlobal;

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 +14,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList

private final Device device;
private IBinder display;
VirtualDisplay virtualDisplay;

public ScreenCapture(Device device) {
this.device = device;
Expand All @@ -31,12 +35,33 @@ public void start(Surface surface) {
Rect unlockedVideoRect = screenInfo.getUnlockedVideoSize().toRect();
int videoRotation = screenInfo.getVideoRotation();
int layerStack = device.getLayerStack();
Rect videoRect = screenInfo.getVideoSize().toRect();

if (display != null) {
SurfaceControl.destroyDisplay(display);
}
display = createDisplay();
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack);
try {
virtualDisplay = DisplayManager.createVirtualDisplay(
"displayManager VirtualDisplay",
videoRect.width(),
videoRect.height(),
0,
surface);
Ln.i("Using the DisplayManager system API.");
} catch (Exception displayManagerException) {
try {
virtualDisplay = MediaProjectionGlobal.createVirtualDisplay(
"mediaProjection global",
videoRect.width(),
videoRect.height(),
0,
surface);
Ln.i("Using the MediaProjectionGlobal system API.");
} catch (NoSuchMethodException | NullPointerException mediaProjectionGlobalException){
display = createDisplay();
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack);
}
}
}

@Override
Expand All @@ -46,6 +71,9 @@ public void release() {
if (display != null) {
SurfaceControl.destroyDisplay(display);
}
if (virtualDisplay != null){
virtualDisplay.release();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.genymobile.scrcpy.wrappers;

import android.hardware.display.VirtualDisplay;
import android.view.Display;
import android.view.Surface;
import com.genymobile.scrcpy.Command;
import com.genymobile.scrcpy.DisplayInfo;
import com.genymobile.scrcpy.Ln;
Expand All @@ -8,6 +11,7 @@
import android.view.Display;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -87,6 +91,16 @@ public DisplayInfo getDisplayInfo(int displayId) {
}
}

public static VirtualDisplay createVirtualDisplay(String name, int width, int height,
int displayIdToMirror, Surface surface)
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
java.lang.Class<?> displayManagerClass =
java.lang.Class.forName("android.hardware.display.DisplayManager");
return (VirtualDisplay) displayManagerClass.getMethod("createVirtualDisplay",
String.class, int.class, int.class, int.class, Surface.class)
.invoke(null, name, width, height, displayIdToMirror, surface);
}

public int[] getDisplayIds() {
try {
return (int[]) manager.getClass().getMethod("getDisplayIds").invoke(manager);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.genymobile.scrcpy.wrappers;

import android.hardware.display.VirtualDisplay;
import android.view.Surface;
import com.genymobile.scrcpy.Ln;
import java.lang.reflect.Method;
import android.os.Build;

/**
* A wrapper for system API android.media.projection.MediaProjectionGlobal.
*/
public final class MediaProjectionGlobal {

private static java.lang.Class<?> MediaProjectionGlobalClass;
private static Method getInstanceMethod;
private static Method createVirtualDisplayMethod;

static {
try {
MediaProjectionGlobalClass = java.lang.Class.forName("android.media.projection.MediaProjectionGlobal");
} catch (ClassNotFoundException e) {
MediaProjectionGlobalClass = null;
}
}

private static Method getGetInstanceMethod() throws NoSuchMethodException {
if (MediaProjectionGlobalClass == null) {
throw new NullPointerException("MediaProjectionGlobalClass is null");
}
if (getInstanceMethod == null) {
getInstanceMethod = MediaProjectionGlobalClass.getMethod("getInstance");
}
return getInstanceMethod;
}

// String name, int width, int height, int displayIdToMirror
private static Method getCreateVirtualDisplayMethod() throws NoSuchMethodException {
if (MediaProjectionGlobalClass == null) {
throw new NullPointerException("MediaProjectionGlobalClass is null");
}
if (createVirtualDisplayMethod == null) {
createVirtualDisplayMethod =
MediaProjectionGlobalClass.getMethod(
"createVirtualDisplay", String.class, int.class, int.class, int.class, Surface.class);
}
return createVirtualDisplayMethod;
}

public static VirtualDisplay createVirtualDisplay(
String name, int width, int height, int displayIdToMirror, Surface surface)
throws NoSuchMethodException {
try {
Object instance = getGetInstanceMethod().invoke(null);
if (instance == null) {
Ln.e("instance == null!");
}
return (VirtualDisplay)
getCreateVirtualDisplayMethod()
.invoke(instance, name, width, height, displayIdToMirror, surface);
} catch (ReflectiveOperationException e) {
Ln.e("Could not invoke method", e);
return null;
}
}

private MediaProjectionGlobal() {}
}