From f2dee20a207b9906574d9b3d62a0ab2585dade20 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 5 Feb 2023 09:50:51 +0100 Subject: [PATCH] Set power mode on all physical displays Android 10 and above support multiple physical displays. Apply power mode to all of them. Fixes #3716 --- .../java/com/genymobile/scrcpy/Device.java | 20 ++++++++++ .../scrcpy/wrappers/SurfaceControl.java | 37 ++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/Device.java b/server/src/main/java/com/genymobile/scrcpy/Device.java index 97b25b22..30e64fd7 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Device.java +++ b/server/src/main/java/com/genymobile/scrcpy/Device.java @@ -277,6 +277,26 @@ public final class Device { * @param mode one of the {@code POWER_MODE_*} constants */ public static boolean setScreenPowerMode(int mode) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // Change the power mode for all physical displays + long[] physicalDisplayIds = SurfaceControl.getPhysicalDisplayIds(); + if (physicalDisplayIds == null) { + Ln.e("Could not get physical display ids"); + return false; + } + + boolean allOk = true; + for (long physicalDisplayId : physicalDisplayIds) { + IBinder binder = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId); + boolean ok = SurfaceControl.setDisplayPowerMode(binder, mode); + if (!ok) { + allOk = false; + } + } + return allOk; + } + + // Older Android versions, only 1 display IBinder d = SurfaceControl.getBuiltInDisplay(); if (d == null) { Ln.e("Could not get built-in display"); diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/SurfaceControl.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/SurfaceControl.java index 8fbb860b..595ee6d4 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/SurfaceControl.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/SurfaceControl.java @@ -30,6 +30,8 @@ public final class SurfaceControl { private static Method getBuiltInDisplayMethod; private static Method setDisplayPowerModeMethod; + private static Method getPhysicalDisplayTokenMethod; + private static Method getPhysicalDisplayIdsMethod; private SurfaceControl() { // only static methods @@ -98,7 +100,6 @@ public final class SurfaceControl { } public static IBinder getBuiltInDisplay() { - try { Method method = getGetBuiltInDisplayMethod(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { @@ -114,6 +115,40 @@ public final class SurfaceControl { } } + 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 (InvocationTargetException | IllegalAccessException | NoSuchMethodException 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 long[] getPhysicalDisplayIds() { + try { + Method method = getGetPhysicalDisplayIdsMethod(); + return (long[]) method.invoke(null); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException 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);