mirror of https://github.com/Genymobile/scrcpy
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
6.2 KiB
Java
186 lines
6.2 KiB
Java
package com.genymobile.scrcpy.wrappers;
|
|
|
|
import com.genymobile.scrcpy.Ln;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.graphics.Rect;
|
|
import android.os.Build;
|
|
import android.os.IBinder;
|
|
import android.view.Surface;
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
@SuppressLint("PrivateApi")
|
|
public final class SurfaceControl {
|
|
|
|
private static final Class<?> CLASS;
|
|
|
|
// see <https://android.googlesource.com/platform/frameworks/base.git/+/pie-release-2/core/java/android/view/SurfaceControl.java#305>
|
|
public static final int POWER_MODE_OFF = 0;
|
|
public static final int POWER_MODE_NORMAL = 2;
|
|
|
|
static {
|
|
try {
|
|
CLASS = Class.forName("android.view.SurfaceControl");
|
|
} catch (ClassNotFoundException e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
private static Method getBuiltInDisplayMethod;
|
|
private static Method setDisplayPowerModeMethod;
|
|
private static Method getPhysicalDisplayTokenMethod;
|
|
private static Method getPhysicalDisplayIdsMethod;
|
|
|
|
private SurfaceControl() {
|
|
// only static methods
|
|
}
|
|
|
|
public static void openTransaction() {
|
|
try {
|
|
CLASS.getMethod("openTransaction").invoke(null);
|
|
} catch (Exception e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
public static void closeTransaction() {
|
|
try {
|
|
CLASS.getMethod("closeTransaction").invoke(null);
|
|
} catch (Exception e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
public static void setDisplayProjection(IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect) {
|
|
try {
|
|
CLASS.getMethod("setDisplayProjection", IBinder.class, int.class, Rect.class, Rect.class)
|
|
.invoke(null, displayToken, orientation, layerStackRect, displayRect);
|
|
} catch (Exception e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
|
|
try {
|
|
CLASS.getMethod("setDisplayLayerStack", IBinder.class, int.class).invoke(null, displayToken, layerStack);
|
|
} catch (Exception e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
public static void setDisplaySurface(IBinder displayToken, Surface surface) {
|
|
try {
|
|
CLASS.getMethod("setDisplaySurface", IBinder.class, Surface.class).invoke(null, displayToken, surface);
|
|
} catch (Exception e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
private static Method getGetBuiltInDisplayMethod() throws NoSuchMethodException {
|
|
if (getBuiltInDisplayMethod == null) {
|
|
// the method signature has changed in Android Q
|
|
// <https://github.com/Genymobile/scrcpy/issues/586>
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
|
getBuiltInDisplayMethod = CLASS.getMethod("getBuiltInDisplay", int.class);
|
|
} else {
|
|
getBuiltInDisplayMethod = CLASS.getMethod("getInternalDisplayToken");
|
|
}
|
|
}
|
|
return getBuiltInDisplayMethod;
|
|
}
|
|
|
|
public static IBinder getBuiltInDisplay() {
|
|
try {
|
|
Method method = getGetBuiltInDisplayMethod();
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
|
// call getBuiltInDisplay(0)
|
|
return (IBinder) method.invoke(null, 0);
|
|
}
|
|
|
|
// call getInternalDisplayToken()
|
|
return (IBinder) method.invoke(null);
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static Method getGetPhysicalDisplayTokenMethod() throws NoSuchMethodException {
|
|
if (getPhysicalDisplayTokenMethod == null) {
|
|
getPhysicalDisplayTokenMethod = CLASS.getMethod("getPhysicalDisplayToken", long.class);
|
|
}
|
|
return getPhysicalDisplayTokenMethod;
|
|
}
|
|
|
|
public static IBinder getPhysicalDisplayToken(long physicalDisplayId) {
|
|
try {
|
|
Method method = getGetPhysicalDisplayTokenMethod();
|
|
return (IBinder) method.invoke(null, physicalDisplayId);
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static Method getGetPhysicalDisplayIdsMethod() throws NoSuchMethodException {
|
|
if (getPhysicalDisplayIdsMethod == null) {
|
|
getPhysicalDisplayIdsMethod = CLASS.getMethod("getPhysicalDisplayIds");
|
|
}
|
|
return getPhysicalDisplayIdsMethod;
|
|
}
|
|
|
|
public static boolean hasPhysicalDisplayIdsMethod() {
|
|
try {
|
|
getGetPhysicalDisplayIdsMethod();
|
|
return true;
|
|
} catch (NoSuchMethodException e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static long[] getPhysicalDisplayIds() {
|
|
try {
|
|
Method method = getGetPhysicalDisplayIdsMethod();
|
|
return (long[]) method.invoke(null);
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static Method getSetDisplayPowerModeMethod() throws NoSuchMethodException {
|
|
if (setDisplayPowerModeMethod == null) {
|
|
setDisplayPowerModeMethod = CLASS.getMethod("setDisplayPowerMode", IBinder.class, int.class);
|
|
}
|
|
return setDisplayPowerModeMethod;
|
|
}
|
|
|
|
public static boolean setDisplayPowerMode(IBinder displayToken, int mode) {
|
|
try {
|
|
Method method = getSetDisplayPowerModeMethod();
|
|
method.invoke(null, displayToken, mode);
|
|
return true;
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static void destroyDisplay(IBinder displayToken) {
|
|
try {
|
|
CLASS.getMethod("destroyDisplay", IBinder.class).invoke(null, displayToken);
|
|
} catch (Exception e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
}
|