From 75e2b1e930bb244a464390142f226f02f253e7ed Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 3 Jul 2022 00:48:49 +0200 Subject: [PATCH] Add option --install When this flag is set, the scrcpy is installed rather than pushed to /data/local/tmp. --- app/scrcpy.1 | 4 +++ app/src/cli.c | 10 +++++++ app/src/options.c | 1 + app/src/options.h | 1 + app/src/scrcpy.c | 1 + app/src/server.c | 72 ++++++++++++++++++++++++++++++++++++++++++++--- app/src/server.h | 1 + 7 files changed, 86 insertions(+), 4 deletions(-) diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 7cb893b7..2717d82c 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -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). diff --git a/app/src/cli.c b/app/src/cli.c index 538dd3e7..4d731cab 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -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; diff --git a/app/src/options.c b/app/src/options.c index 8b2624d9..320ac9ce 100644 --- a/app/src/options.c +++ b/app/src/options.c @@ -65,4 +65,5 @@ const struct scrcpy_options scrcpy_options_default = { .cleanup = true, .start_fps_counter = false, .power_on = true, + .install = false, }; diff --git a/app/src/options.h b/app/src/options.h index 7e542c06..b0e32ccd 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -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; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 3588e9ae..add6168d 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -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 = { diff --git a/app/src/server.c b/app/src/server.c index ee1f9fbc..54de32c0 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -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; } diff --git a/app/src/server.h b/app/src/server.h index 49ba83c1..68aa59ef 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -48,6 +48,7 @@ struct sc_server_params { bool select_tcpip; bool cleanup; bool power_on; + bool install; }; struct sc_server {