Add option --install

When this flag is set, the scrcpy is installed rather than pushed to
/data/local/tmp.
This commit is contained in:
Romain Vimont 2022-07-03 00:48:49 +02:00
parent 0fe74f8e96
commit 75e2b1e930
7 changed files with 86 additions and 4 deletions

View file

@ -110,6 +110,10 @@ However, the option is only available when the HID keyboard is enabled (or a phy
Also see \fB\-\-hid\-mouse\fR.
.TP
.B \-\-install
Install the server (via "adb install") rather than pushing it to /data/local/tmp (via "adb push").
.TP
.B \-\-legacy\-paste
Inject computer clipboard text as a sequence of key events on Ctrl+v (like MOD+Shift+v).

View file

@ -57,6 +57,7 @@
#define OPT_NO_CLEANUP 1037
#define OPT_PRINT_FPS 1038
#define OPT_NO_POWER_ON 1039
#define OPT_INSTALL 1040
struct sc_option {
char shortopt;
@ -207,6 +208,12 @@ static const struct sc_option options[] = {
.longopt = "help",
.text = "Print this help.",
},
{
.longopt_id = OPT_INSTALL,
.longopt = "install",
.text = "Install the server (via 'adb install') rather than pushing "
"it to /data/local/tmp (via 'adb push').",
},
{
.longopt_id = OPT_LEGACY_PASTE,
.longopt = "legacy-paste",
@ -1610,6 +1617,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
case OPT_PRINT_FPS:
opts->start_fps_counter = true;
break;
case OPT_INSTALL:
opts->install = true;
break;
case OPT_OTG:
#ifdef HAVE_USB
opts->otg = true;

View file

@ -65,4 +65,5 @@ const struct scrcpy_options scrcpy_options_default = {
.cleanup = true,
.start_fps_counter = false,
.power_on = true,
.install = false,
};

View file

@ -140,6 +140,7 @@ struct scrcpy_options {
bool cleanup;
bool start_fps_counter;
bool power_on;
bool install;
};
extern const struct scrcpy_options scrcpy_options_default;

View file

@ -325,6 +325,7 @@ scrcpy(struct scrcpy_options *options) {
.tcpip_dst = options->tcpip_dst,
.cleanup = options->cleanup,
.power_on = options->power_on,
.install = options->install,
};
static const struct sc_server_callbacks cbs = {

View file

@ -15,6 +15,7 @@
#include "util/str.h"
#define SC_SERVER_FILENAME "scrcpy-server.apk"
#define SC_SERVER_PACKAGE "com.genymobile.scrcpy"
#define SC_SERVER_PATH_DEFAULT PREFIX "/share/scrcpy/" SC_SERVER_FILENAME
#define SC_DEVICE_SERVER_PATH "/data/local/tmp/scrcpy-server.apk"
@ -104,7 +105,7 @@ error:
}
static bool
push_server(struct sc_intr *intr, const char *serial) {
push_server(struct sc_intr *intr, const char *serial, bool install) {
char *server_path = get_server_path();
if (!server_path) {
return false;
@ -114,7 +115,28 @@ push_server(struct sc_intr *intr, const char *serial) {
free(server_path);
return false;
}
bool ok = sc_adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH, 0);
bool ok;
if (install) {
char *version = sc_adb_get_installed_apk_version(intr, serial, 0);
bool same_version = version && !strcmp(version, SCRCPY_VERSION);
free(version);
if (same_version) {
LOGI("Server " SCRCPY_VERSION " already installed");
ok = true;
} else {
LOGI("Installing server " SCRCPY_VERSION);
// If a server with a different signature is installed, or if a
// newer server is already installed, we must uninstall it first.
ok = sc_adb_uninstall(intr, serial, SC_SERVER_PACKAGE,
SC_ADB_SILENT);
(void) ok; // expected to fail if it is not installed
ok = sc_adb_install(intr, serial, server_path, 0);
}
} else {
ok = sc_adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH, 0);
}
free(server_path);
return ok;
}
@ -152,6 +174,38 @@ sc_server_sleep(struct sc_server *server, sc_tick deadline) {
return !stopped;
}
static char *
get_classpath_cmd(struct sc_intr *intr, const char *serial, bool install) {
if (!install) {
// In push mode, the path is known statically
char *cp = strdup("CLASSPATH=" SC_DEVICE_SERVER_PATH);
if (!cp) {
LOG_OOM();
}
return cp;
}
char *apk_path = sc_adb_get_installed_apk_path(intr, serial, 0);
if (!apk_path) {
LOGE("Could not get device apk path");
return NULL;
}
#define PREFIX_SIZE (sizeof("CLASSPATH=") - 1)
size_t len = strlen(apk_path);
char *cp = malloc(PREFIX_SIZE + len + 1);
if (!cp) {
LOG_OOM();
free(apk_path);
return NULL;
}
memcpy(cp, "CLASSPATH=", PREFIX_SIZE);
memcpy(cp + PREFIX_SIZE, apk_path, len + 1);
free(apk_path);
return cp;
}
static sc_pid
execute_server(struct sc_server *server,
const struct sc_server_params *params) {
@ -160,13 +214,20 @@ execute_server(struct sc_server *server,
const char *serial = server->serial;
assert(serial);
char *classpath = get_classpath_cmd(&server->intr, serial, params->install);
if (!classpath) {
return SC_PROCESS_NONE;
}
LOGD("Using %s", classpath);
const char *cmd[128];
unsigned count = 0;
cmd[count++] = sc_adb_get_executable();
cmd[count++] = "-s";
cmd[count++] = serial;
cmd[count++] = "shell";
cmd[count++] = "CLASSPATH=" SC_DEVICE_SERVER_PATH;
cmd[count++] = classpath;
cmd[count++] = "app_process";
#ifdef SERVER_DEBUGGER
@ -272,6 +333,8 @@ execute_server(struct sc_server *server,
pid = sc_adb_execute(cmd, 0);
end:
free(classpath);
for (unsigned i = dyn_idx; i < count; ++i) {
free((char *) cmd[i]);
}
@ -755,8 +818,9 @@ run_server(void *data) {
assert(serial);
LOGD("Device serial: %s", serial);
ok = push_server(&server->intr, serial);
ok = push_server(&server->intr, serial, params->install);
if (!ok) {
LOGE("Failed to push server");
goto error_connection_failed;
}

View file

@ -48,6 +48,7 @@ struct sc_server_params {
bool select_tcpip;
bool cleanup;
bool power_on;
bool install;
};
struct sc_server {