Add an option to keep the device awake
Add an option to prevent the device to sleep: scrcpy --stay-awake scrcpy -w The initial state is restored on exit. Fixes #631 <https://github.com/Genymobile/scrcpy/issues/631>
This commit is contained in:
parent
828327365a
commit
c77024314d
10 changed files with 93 additions and 15 deletions
20
README.md
20
README.md
|
@ -396,6 +396,18 @@ The list of display ids can be retrieved by:
|
||||||
adb shell dumpsys display # search "mDisplayId=" in the output
|
adb shell dumpsys display # search "mDisplayId=" in the output
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Stay awake
|
||||||
|
|
||||||
|
To prevent the device to sleep after some delay:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scrcpy --stay-awake
|
||||||
|
scrcpy -w
|
||||||
|
```
|
||||||
|
|
||||||
|
The initial state is restored when scrcpy is closed.
|
||||||
|
|
||||||
|
|
||||||
#### Turn screen off
|
#### Turn screen off
|
||||||
|
|
||||||
It is possible to turn the device screen off while mirroring on start with a
|
It is possible to turn the device screen off while mirroring on start with a
|
||||||
|
@ -410,6 +422,14 @@ Or by pressing `Ctrl`+`o` at any time.
|
||||||
|
|
||||||
To turn it back on, press `POWER` (or `Ctrl`+`p`).
|
To turn it back on, press `POWER` (or `Ctrl`+`p`).
|
||||||
|
|
||||||
|
It can be useful to also prevent the device to sleep:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scrcpy --turn-screen-off --stay-awake
|
||||||
|
scrcpy -Sw
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Render expired frames
|
#### Render expired frames
|
||||||
|
|
||||||
By default, to minimize latency, _scrcpy_ always renders the last decoded frame
|
By default, to minimize latency, _scrcpy_ always renders the last decoded frame
|
||||||
|
|
|
@ -144,6 +144,10 @@ It only shows physical touches (not clicks from scrcpy).
|
||||||
.B \-v, \-\-version
|
.B \-v, \-\-version
|
||||||
Print the version of scrcpy.
|
Print the version of scrcpy.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-w, \-\-stay-awake
|
||||||
|
Keep the device on while scrcpy is running.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-window\-borderless
|
.B \-\-window\-borderless
|
||||||
Disable window decorations (display borderless window).
|
Disable window decorations (display borderless window).
|
||||||
|
|
|
@ -137,6 +137,9 @@ scrcpy_print_usage(const char *arg0) {
|
||||||
" -v, --version\n"
|
" -v, --version\n"
|
||||||
" Print the version of scrcpy.\n"
|
" Print the version of scrcpy.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" -w, --stay-awake\n"
|
||||||
|
" Keep the device on while scrcpy is running.\n"
|
||||||
|
"\n"
|
||||||
" --window-borderless\n"
|
" --window-borderless\n"
|
||||||
" Disable window decorations (display borderless window).\n"
|
" Disable window decorations (display borderless window).\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -497,6 +500,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
{"rotation", required_argument, NULL, OPT_ROTATION},
|
{"rotation", required_argument, NULL, OPT_ROTATION},
|
||||||
{"serial", required_argument, NULL, 's'},
|
{"serial", required_argument, NULL, 's'},
|
||||||
{"show-touches", no_argument, NULL, 't'},
|
{"show-touches", no_argument, NULL, 't'},
|
||||||
|
{"stay-awake", no_argument, NULL, 'w'},
|
||||||
{"turn-screen-off", no_argument, NULL, 'S'},
|
{"turn-screen-off", no_argument, NULL, 'S'},
|
||||||
{"version", no_argument, NULL, 'v'},
|
{"version", no_argument, NULL, 'v'},
|
||||||
{"window-title", required_argument, NULL, OPT_WINDOW_TITLE},
|
{"window-title", required_argument, NULL, OPT_WINDOW_TITLE},
|
||||||
|
@ -514,7 +518,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
optind = 0; // reset to start from the first argument in tests
|
optind = 0; // reset to start from the first argument in tests
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:StTv", long_options,
|
while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:StTvw", long_options,
|
||||||
NULL)) != -1) {
|
NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
|
@ -594,6 +598,9 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
case 'v':
|
case 'v':
|
||||||
args->version = true;
|
args->version = true;
|
||||||
break;
|
break;
|
||||||
|
case 'w':
|
||||||
|
opts->stay_awake = true;
|
||||||
|
break;
|
||||||
case OPT_RENDER_EXPIRED_FRAMES:
|
case OPT_RENDER_EXPIRED_FRAMES:
|
||||||
opts->render_expired_frames = true;
|
opts->render_expired_frames = true;
|
||||||
break;
|
break;
|
||||||
|
@ -676,5 +683,10 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!opts->control && opts->stay_awake) {
|
||||||
|
LOGE("Could not request to stay awake if control is disabled");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,6 +278,7 @@ scrcpy(const struct scrcpy_options *options) {
|
||||||
.control = options->control,
|
.control = options->control,
|
||||||
.display_id = options->display_id,
|
.display_id = options->display_id,
|
||||||
.show_touches = options->show_touches,
|
.show_touches = options->show_touches,
|
||||||
|
.stay_awake = options->stay_awake,
|
||||||
};
|
};
|
||||||
if (!server_start(&server, options->serial, ¶ms)) {
|
if (!server_start(&server, options->serial, ¶ms)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct scrcpy_options {
|
||||||
bool prefer_text;
|
bool prefer_text;
|
||||||
bool window_borderless;
|
bool window_borderless;
|
||||||
bool mipmaps;
|
bool mipmaps;
|
||||||
|
bool stay_awake;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRCPY_OPTIONS_DEFAULT { \
|
#define SCRCPY_OPTIONS_DEFAULT { \
|
||||||
|
@ -72,6 +73,7 @@ struct scrcpy_options {
|
||||||
.prefer_text = false, \
|
.prefer_text = false, \
|
||||||
.window_borderless = false, \
|
.window_borderless = false, \
|
||||||
.mipmaps = true, \
|
.mipmaps = true, \
|
||||||
|
.stay_awake = false, \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -269,6 +269,7 @@ execute_server(struct server *server, const struct server_params *params) {
|
||||||
params->control ? "true" : "false",
|
params->control ? "true" : "false",
|
||||||
display_id_string,
|
display_id_string,
|
||||||
params->show_touches ? "true" : "false",
|
params->show_touches ? "true" : "false",
|
||||||
|
params->stay_awake ? "true" : "false",
|
||||||
};
|
};
|
||||||
#ifdef SERVER_DEBUGGER
|
#ifdef SERVER_DEBUGGER
|
||||||
LOGI("Server debugger waiting for a client on device port "
|
LOGI("Server debugger waiting for a client on device port "
|
||||||
|
|
|
@ -52,6 +52,7 @@ struct server_params {
|
||||||
bool control;
|
bool control;
|
||||||
uint16_t display_id;
|
uint16_t display_id;
|
||||||
bool show_touches;
|
bool show_touches;
|
||||||
|
bool stay_awake;
|
||||||
};
|
};
|
||||||
|
|
||||||
// init default values
|
// init default values
|
||||||
|
|
|
@ -19,18 +19,18 @@ public final class CleanUp {
|
||||||
// not instantiable
|
// not instantiable
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void configure(boolean disableShowTouches) throws IOException {
|
public static void configure(boolean disableShowTouches, int restoreStayOn) throws IOException {
|
||||||
boolean needProcess = disableShowTouches;
|
boolean needProcess = disableShowTouches || restoreStayOn != -1;
|
||||||
if (needProcess) {
|
if (needProcess) {
|
||||||
startProcess(disableShowTouches);
|
startProcess(disableShowTouches, restoreStayOn);
|
||||||
} else {
|
} else {
|
||||||
// There is no additional clean up to do when scrcpy dies
|
// There is no additional clean up to do when scrcpy dies
|
||||||
unlinkSelf();
|
unlinkSelf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startProcess(boolean disableShowTouches) throws IOException {
|
private static void startProcess(boolean disableShowTouches, int restoreStayOn) throws IOException {
|
||||||
String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(disableShowTouches)};
|
String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(disableShowTouches), String.valueOf(restoreStayOn)};
|
||||||
|
|
||||||
ProcessBuilder builder = new ProcessBuilder(cmd);
|
ProcessBuilder builder = new ProcessBuilder(cmd);
|
||||||
builder.environment().put("CLASSPATH", SERVER_PATH);
|
builder.environment().put("CLASSPATH", SERVER_PATH);
|
||||||
|
@ -58,13 +58,20 @@ public final class CleanUp {
|
||||||
Ln.i("Cleaning up");
|
Ln.i("Cleaning up");
|
||||||
|
|
||||||
boolean disableShowTouches = Boolean.parseBoolean(args[0]);
|
boolean disableShowTouches = Boolean.parseBoolean(args[0]);
|
||||||
|
int restoreStayOn = Integer.parseInt(args[1]);
|
||||||
|
|
||||||
if (disableShowTouches) {
|
if (disableShowTouches || restoreStayOn != -1) {
|
||||||
ServiceManager serviceManager = new ServiceManager();
|
ServiceManager serviceManager = new ServiceManager();
|
||||||
try (ContentProvider settings = serviceManager.getActivityManager().createSettingsProvider()) {
|
try (ContentProvider settings = serviceManager.getActivityManager().createSettingsProvider()) {
|
||||||
|
if (disableShowTouches) {
|
||||||
Ln.i("Disabling \"show touches\"");
|
Ln.i("Disabling \"show touches\"");
|
||||||
settings.putValue(ContentProvider.TABLE_SYSTEM, "show_touches", "0");
|
settings.putValue(ContentProvider.TABLE_SYSTEM, "show_touches", "0");
|
||||||
}
|
}
|
||||||
|
if (restoreStayOn != -1) {
|
||||||
|
Ln.i("Restoring \"stay awake\"");
|
||||||
|
settings.putValue(ContentProvider.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(restoreStayOn));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ public class Options {
|
||||||
private boolean control;
|
private boolean control;
|
||||||
private int displayId;
|
private int displayId;
|
||||||
private boolean showTouches;
|
private boolean showTouches;
|
||||||
|
private boolean stayAwake;
|
||||||
|
|
||||||
public int getMaxSize() {
|
public int getMaxSize() {
|
||||||
return maxSize;
|
return maxSize;
|
||||||
|
@ -93,4 +94,12 @@ public class Options {
|
||||||
public void setShowTouches(boolean showTouches) {
|
public void setShowTouches(boolean showTouches) {
|
||||||
this.showTouches = showTouches;
|
this.showTouches = showTouches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getStayAwake() {
|
||||||
|
return stayAwake;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStayAwake(boolean stayAwake) {
|
||||||
|
this.stayAwake = stayAwake;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.genymobile.scrcpy.wrappers.ContentProvider;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec;
|
||||||
|
import android.os.BatteryManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -20,15 +21,32 @@ public final class Server {
|
||||||
final Device device = new Device(options);
|
final Device device = new Device(options);
|
||||||
|
|
||||||
boolean mustDisableShowTouchesOnCleanUp = false;
|
boolean mustDisableShowTouchesOnCleanUp = false;
|
||||||
if (options.getShowTouches()) {
|
int restoreStayOn = -1;
|
||||||
|
if (options.getShowTouches() || options.getStayAwake()) {
|
||||||
try (ContentProvider settings = device.createSettingsProvider()) {
|
try (ContentProvider settings = device.createSettingsProvider()) {
|
||||||
|
if (options.getShowTouches()) {
|
||||||
String oldValue = settings.getAndPutValue(ContentProvider.TABLE_SYSTEM, "show_touches", "1");
|
String oldValue = settings.getAndPutValue(ContentProvider.TABLE_SYSTEM, "show_touches", "1");
|
||||||
// If "show touches" was disabled, it must be disabled back on clean up
|
// If "show touches" was disabled, it must be disabled back on clean up
|
||||||
mustDisableShowTouchesOnCleanUp = !"1".equals(oldValue);
|
mustDisableShowTouchesOnCleanUp = !"1".equals(oldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.getStayAwake()) {
|
||||||
|
int stayOn = BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB | BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||||
|
String oldValue = settings.getAndPutValue(ContentProvider.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(stayOn));
|
||||||
|
try {
|
||||||
|
restoreStayOn = Integer.parseInt(oldValue);
|
||||||
|
if (restoreStayOn == stayOn) {
|
||||||
|
// No need to restore
|
||||||
|
restoreStayOn = -1;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
restoreStayOn = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CleanUp.configure(mustDisableShowTouchesOnCleanUp);
|
CleanUp.configure(mustDisableShowTouchesOnCleanUp, restoreStayOn);
|
||||||
|
|
||||||
boolean tunnelForward = options.isTunnelForward();
|
boolean tunnelForward = options.isTunnelForward();
|
||||||
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
|
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
|
||||||
|
@ -91,7 +109,7 @@ public final class Server {
|
||||||
"The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")");
|
"The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
final int expectedParameters = 11;
|
final int expectedParameters = 12;
|
||||||
if (args.length != expectedParameters) {
|
if (args.length != expectedParameters) {
|
||||||
throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters");
|
throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters");
|
||||||
}
|
}
|
||||||
|
@ -129,6 +147,9 @@ public final class Server {
|
||||||
boolean showTouches = Boolean.parseBoolean(args[10]);
|
boolean showTouches = Boolean.parseBoolean(args[10]);
|
||||||
options.setShowTouches(showTouches);
|
options.setShowTouches(showTouches);
|
||||||
|
|
||||||
|
boolean stayAwake = Boolean.parseBoolean(args[11]);
|
||||||
|
options.setStayAwake(stayAwake);
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue