Refactor display power mode

Accept a single boolean "on" rather than a "mode" (which, in practice,
could only take 2 values: NORMAL and OFF).

Also rename "screen power mode" to "display power".

PR #5418 <https://github.com/Genymobile/scrcpy/pull/5418>
This commit is contained in:
Romain Vimont 2024-10-28 23:56:17 +01:00
parent acff5b005c
commit 58a0fbbf2e
11 changed files with 71 additions and 93 deletions

View File

@ -22,9 +22,6 @@
#define MOTIONEVENT_ACTION_LABEL(value) \
ENUM_TO_LABEL(android_motionevent_action_labels, value)
#define SCREEN_POWER_MODE_LABEL(value) \
ENUM_TO_LABEL(screen_power_mode_labels, value)
static const char *const android_keyevent_action_labels[] = {
"down",
"up",
@ -47,14 +44,6 @@ static const char *const android_motionevent_action_labels[] = {
"btn-release",
};
static const char *const screen_power_mode_labels[] = {
"off",
"doze",
"normal",
"doze-suspend",
"suspend",
};
static const char *const copy_key_labels[] = {
"none",
"copy",
@ -158,8 +147,8 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf) {
size_t len = write_string(&buf[10], msg->set_clipboard.text,
SC_CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH);
return 10 + len;
case SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE:
buf[1] = msg->set_screen_power_mode.mode;
case SC_CONTROL_MSG_TYPE_SET_DISPLAY_POWER:
buf[1] = msg->set_display_power.on;
return 2;
case SC_CONTROL_MSG_TYPE_UHID_CREATE:
sc_write16be(&buf[1], msg->uhid_create.id);
@ -268,9 +257,9 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
msg->set_clipboard.paste ? "paste" : "nopaste",
msg->set_clipboard.text);
break;
case SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE:
LOG_CMSG("power mode %s",
SCREEN_POWER_MODE_LABEL(msg->set_screen_power_mode.mode));
case SC_CONTROL_MSG_TYPE_SET_DISPLAY_POWER:
LOG_CMSG("display power %s",
msg->set_display_power.on ? "on" : "off");
break;
case SC_CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL:
LOG_CMSG("expand notification panel");

View File

@ -35,7 +35,7 @@ enum sc_control_msg_type {
SC_CONTROL_MSG_TYPE_COLLAPSE_PANELS,
SC_CONTROL_MSG_TYPE_GET_CLIPBOARD,
SC_CONTROL_MSG_TYPE_SET_CLIPBOARD,
SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE,
SC_CONTROL_MSG_TYPE_SET_DISPLAY_POWER,
SC_CONTROL_MSG_TYPE_ROTATE_DEVICE,
SC_CONTROL_MSG_TYPE_UHID_CREATE,
SC_CONTROL_MSG_TYPE_UHID_INPUT,
@ -44,12 +44,6 @@ enum sc_control_msg_type {
SC_CONTROL_MSG_TYPE_START_APP,
};
enum sc_screen_power_mode {
// see <https://android.googlesource.com/platform/frameworks/base.git/+/pie-release-2/core/java/android/view/SurfaceControl.java#305>
SC_SCREEN_POWER_MODE_OFF = 0,
SC_SCREEN_POWER_MODE_NORMAL = 2,
};
enum sc_copy_key {
SC_COPY_KEY_NONE,
SC_COPY_KEY_COPY,
@ -95,8 +89,8 @@ struct sc_control_msg {
bool paste;
} set_clipboard;
struct {
enum sc_screen_power_mode mode;
} set_screen_power_mode;
bool on;
} set_display_power;
struct {
uint16_t id;
const char *name; // pointer to static data

View File

@ -203,13 +203,12 @@ set_device_clipboard(struct sc_input_manager *im, bool paste,
}
static void
set_screen_power_mode(struct sc_input_manager *im,
enum sc_screen_power_mode mode) {
set_display_power(struct sc_input_manager *im, bool on) {
assert(im->controller);
struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE;
msg.set_screen_power_mode.mode = mode;
msg.type = SC_CONTROL_MSG_TYPE_SET_DISPLAY_POWER;
msg.set_display_power.on = on;
if (!sc_controller_push_msg(im->controller, &msg)) {
LOGW("Could not request 'set screen power mode'");
@ -415,10 +414,8 @@ sc_input_manager_process_key(struct sc_input_manager *im,
return;
case SDLK_o:
if (control && !repeat && down && !paused) {
enum sc_screen_power_mode mode = shift
? SC_SCREEN_POWER_MODE_NORMAL
: SC_SCREEN_POWER_MODE_OFF;
set_screen_power_mode(im, mode);
bool on = shift;
set_display_power(im, on);
}
return;
case SDLK_z:

View File

@ -873,11 +873,11 @@ aoa_complete:
// everything is set up
if (options->control && options->turn_screen_off) {
struct sc_control_msg msg;
msg.type = SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE;
msg.set_screen_power_mode.mode = SC_SCREEN_POWER_MODE_OFF;
msg.type = SC_CONTROL_MSG_TYPE_SET_DISPLAY_POWER;
msg.set_display_power.on = false;
if (!sc_controller_push_msg(&s->controller, &msg)) {
LOGW("Could not request 'set screen power mode'");
LOGW("Could not request 'set display power'");
}
}

View File

@ -289,11 +289,11 @@ static void test_serialize_set_clipboard_long(void) {
assert(!memcmp(buf, expected, sizeof(expected)));
}
static void test_serialize_set_screen_power_mode(void) {
static void test_serialize_set_display_power(void) {
struct sc_control_msg msg = {
.type = SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE,
.set_screen_power_mode = {
.mode = SC_SCREEN_POWER_MODE_NORMAL,
.type = SC_CONTROL_MSG_TYPE_SET_DISPLAY_POWER,
.set_display_power = {
.on = true,
},
};
@ -302,8 +302,8 @@ static void test_serialize_set_screen_power_mode(void) {
assert(size == 2);
const uint8_t expected[] = {
SC_CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE,
0x02, // SC_SCREEN_POWER_MODE_NORMAL
SC_CONTROL_MSG_TYPE_SET_DISPLAY_POWER,
0x01, // true
};
assert(!memcmp(buf, expected, sizeof(expected)));
}
@ -423,7 +423,7 @@ int main(int argc, char *argv[]) {
test_serialize_get_clipboard();
test_serialize_set_clipboard();
test_serialize_set_clipboard_long();
test_serialize_set_screen_power_mode();
test_serialize_set_display_power();
test_serialize_rotate_device();
test_serialize_uhid_create();
test_serialize_uhid_input();

View File

@ -19,7 +19,7 @@ public final class CleanUp {
private static final int MSG_TYPE_MASK = 0b11;
private static final int MSG_TYPE_RESTORE_STAY_ON = 0;
private static final int MSG_TYPE_DISABLE_SHOW_TOUCHES = 1;
private static final int MSG_TYPE_RESTORE_NORMAL_POWER_MODE = 2;
private static final int MSG_TYPE_RESTORE_DISPLAY_POWER = 2;
private static final int MSG_TYPE_POWER_OFF_SCREEN = 3;
private static final int MSG_PARAM_SHIFT = 2;
@ -63,8 +63,8 @@ public final class CleanUp {
return sendMessage(MSG_TYPE_DISABLE_SHOW_TOUCHES, disableOnExit ? 1 : 0);
}
public boolean setRestoreNormalPowerMode(boolean restoreOnExit) {
return sendMessage(MSG_TYPE_RESTORE_NORMAL_POWER_MODE, restoreOnExit ? 1 : 0);
public boolean setRestoreDisplayPower(boolean restoreOnExit) {
return sendMessage(MSG_TYPE_RESTORE_DISPLAY_POWER, restoreOnExit ? 1 : 0);
}
public boolean setPowerOffScreen(boolean powerOffScreenOnExit) {
@ -86,7 +86,7 @@ public final class CleanUp {
int restoreStayOn = -1;
boolean disableShowTouches = false;
boolean restoreNormalPowerMode = false;
boolean restoreDisplayPower = false;
boolean powerOffScreen = false;
try {
@ -102,8 +102,8 @@ public final class CleanUp {
case MSG_TYPE_DISABLE_SHOW_TOUCHES:
disableShowTouches = param != 0;
break;
case MSG_TYPE_RESTORE_NORMAL_POWER_MODE:
restoreNormalPowerMode = param != 0;
case MSG_TYPE_RESTORE_DISPLAY_POWER:
restoreDisplayPower = param != 0;
break;
case MSG_TYPE_POWER_OFF_SCREEN:
powerOffScreen = param != 0;
@ -143,9 +143,9 @@ public final class CleanUp {
Ln.i("Power off screen");
Device.powerOffScreen(displayId);
}
} else if (restoreNormalPowerMode) {
Ln.i("Restoring normal power mode");
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
} else if (restoreDisplayPower) {
Ln.i("Restoring display power");
Device.setDisplayPower(true);
}
}

View File

@ -17,7 +17,7 @@ public final class ControlMessage {
public static final int TYPE_COLLAPSE_PANELS = 7;
public static final int TYPE_GET_CLIPBOARD = 8;
public static final int TYPE_SET_CLIPBOARD = 9;
public static final int TYPE_SET_SCREEN_POWER_MODE = 10;
public static final int TYPE_SET_DISPLAY_POWER = 10;
public static final int TYPE_ROTATE_DEVICE = 11;
public static final int TYPE_UHID_CREATE = 12;
public static final int TYPE_UHID_INPUT = 13;
@ -34,7 +34,7 @@ public final class ControlMessage {
private int type;
private String text;
private int metaState; // KeyEvent.META_*
private int action; // KeyEvent.ACTION_* or MotionEvent.ACTION_* or POWER_MODE_*
private int action; // KeyEvent.ACTION_* or MotionEvent.ACTION_*
private int keycode; // KeyEvent.KEYCODE_*
private int actionButton; // MotionEvent.BUTTON_*
private int buttons; // MotionEvent.BUTTON_*
@ -49,6 +49,7 @@ public final class ControlMessage {
private long sequence;
private int id;
private byte[] data;
private boolean on;
private ControlMessage() {
}
@ -116,13 +117,10 @@ public final class ControlMessage {
return msg;
}
/**
* @param mode one of the {@code Device.SCREEN_POWER_MODE_*} constants
*/
public static ControlMessage createSetScreenPowerMode(int mode) {
public static ControlMessage createSetDisplayPower(boolean on) {
ControlMessage msg = new ControlMessage();
msg.type = TYPE_SET_SCREEN_POWER_MODE;
msg.action = mode;
msg.type = TYPE_SET_DISPLAY_POWER;
msg.on = on;
return msg;
}
@ -234,4 +232,8 @@ public final class ControlMessage {
public byte[] getData() {
return data;
}
public boolean getOn() {
return on;
}
}

View File

@ -39,8 +39,8 @@ public class ControlMessageReader {
return parseGetClipboard();
case ControlMessage.TYPE_SET_CLIPBOARD:
return parseSetClipboard();
case ControlMessage.TYPE_SET_SCREEN_POWER_MODE:
return parseSetScreenPowerMode();
case ControlMessage.TYPE_SET_DISPLAY_POWER:
return parseSetDisplayPower();
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL:
case ControlMessage.TYPE_COLLAPSE_PANELS:
@ -134,9 +134,9 @@ public class ControlMessageReader {
return ControlMessage.createSetClipboard(sequence, text, paste);
}
private ControlMessage parseSetScreenPowerMode() throws IOException {
int mode = dis.readUnsignedByte();
return ControlMessage.createSetScreenPowerMode(mode);
private ControlMessage parseSetDisplayPower() throws IOException {
boolean on = dis.readBoolean();
return ControlMessage.createSetDisplayPower(on);
}
private ControlMessage parseUhidCreate() throws IOException {

View File

@ -91,7 +91,7 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
private final MotionEvent.PointerProperties[] pointerProperties = new MotionEvent.PointerProperties[PointersState.MAX_POINTERS];
private final MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[PointersState.MAX_POINTERS];
private boolean keepPowerModeOff;
private boolean keepDisplayPowerOff;
public Controller(int displayId, ControlChannel controlChannel, CleanUp cleanUp, boolean clipboardAutosync, boolean powerOn) {
this.displayId = displayId;
@ -270,16 +270,16 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
case ControlMessage.TYPE_SET_CLIPBOARD:
setClipboard(msg.getText(), msg.getPaste(), msg.getSequence());
break;
case ControlMessage.TYPE_SET_SCREEN_POWER_MODE:
case ControlMessage.TYPE_SET_DISPLAY_POWER:
if (supportsInputEvents) {
int mode = msg.getAction();
boolean setPowerModeOk = Device.setScreenPowerMode(mode);
if (setPowerModeOk) {
keepPowerModeOff = mode == Device.POWER_MODE_OFF;
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
boolean on = msg.getOn();
boolean setDisplayPowerOk = Device.setDisplayPower(on);
if (setDisplayPowerOk) {
keepDisplayPowerOff = !on;
Ln.i("Device display turned " + (on ? "on" : "off"));
if (cleanUp != null) {
boolean mustRestoreOnExit = mode != Device.POWER_MODE_NORMAL;
cleanUp.setRestoreNormalPowerMode(mustRestoreOnExit);
boolean mustRestoreOnExit = !on;
cleanUp.setRestoreDisplayPower(mustRestoreOnExit);
}
}
}
@ -310,8 +310,8 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
}
private boolean injectKeycode(int action, int keycode, int repeat, int metaState) {
if (keepPowerModeOff && action == KeyEvent.ACTION_UP && (keycode == KeyEvent.KEYCODE_POWER || keycode == KeyEvent.KEYCODE_WAKEUP)) {
schedulePowerModeOff();
if (keepDisplayPowerOff && action == KeyEvent.ACTION_UP && (keycode == KeyEvent.KEYCODE_POWER || keycode == KeyEvent.KEYCODE_WAKEUP)) {
scheduleDisplayPowerOff();
}
return injectKeyEvent(action, keycode, repeat, metaState, Device.INJECT_MODE_ASYNC);
}
@ -488,12 +488,12 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
}
/**
* Schedule a call to set power mode to off after a small delay.
* Schedule a call to set display power to off after a small delay.
*/
private static void schedulePowerModeOff() {
private static void scheduleDisplayPowerOff() {
EXECUTOR.schedule(() -> {
Ln.i("Forcing screen off");
Device.setScreenPowerMode(Device.POWER_MODE_OFF);
Ln.i("Forcing display off");
Device.setDisplayPower(false);
}, 200, TimeUnit.MILLISECONDS);
}
@ -509,8 +509,8 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
return true;
}
if (keepPowerModeOff) {
schedulePowerModeOff();
if (keepDisplayPowerOff) {
scheduleDisplayPowerOff();
}
return pressReleaseKeycode(KeyEvent.KEYCODE_POWER, Device.INJECT_MODE_ASYNC);
}

View File

@ -126,10 +126,7 @@ public final class Device {
return clipboardManager.setText(text);
}
/**
* @param mode one of the {@code POWER_MODE_*} constants
*/
public static boolean setScreenPowerMode(int mode) {
public static boolean setDisplayPower(boolean on) {
boolean applyToMultiPhysicalDisplays = Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10;
if (applyToMultiPhysicalDisplays
@ -142,6 +139,7 @@ public final class Device {
applyToMultiPhysicalDisplays = false;
}
int mode = on ? POWER_MODE_NORMAL : POWER_MODE_OFF;
if (applyToMultiPhysicalDisplays) {
// On Android 14, these internal methods have been moved to DisplayControl
boolean useDisplayControl =

View File

@ -1,7 +1,5 @@
package com.genymobile.scrcpy.control;
import com.genymobile.scrcpy.device.Device;
import android.view.KeyEvent;
import android.view.MotionEvent;
import org.junit.Assert;
@ -285,19 +283,19 @@ public class ControlMessageReaderTest {
}
@Test
public void testParseSetScreenPowerMode() throws IOException {
public void testParseSetDisplayPower() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlMessage.TYPE_SET_SCREEN_POWER_MODE);
dos.writeByte(Device.POWER_MODE_NORMAL);
dos.writeByte(ControlMessage.TYPE_SET_DISPLAY_POWER);
dos.writeBoolean(true);
byte[] packet = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(packet);
ControlMessageReader reader = new ControlMessageReader(bis);
ControlMessage event = reader.read();
Assert.assertEquals(ControlMessage.TYPE_SET_SCREEN_POWER_MODE, event.getType());
Assert.assertEquals(Device.POWER_MODE_NORMAL, event.getAction());
Assert.assertEquals(ControlMessage.TYPE_SET_DISPLAY_POWER, event.getType());
Assert.assertTrue(event.getOn());
Assert.assertEquals(-1, bis.read()); // EOS
}