Compare commits

...

12 Commits

Author SHA1 Message Date
4db97531e8 Upgrade libusb (1.0.26) for Windows
Upgrade and enable libusb support for Windows 32-bit builds.

Refs #3011 <https://github.com/Genymobile/scrcpy/pull/3011>
Fixes #3204 <https://github.com/Genymobile/scrcpy/issues/3204>
PR #3206 <https://github.com/Genymobile/scrcpy/pull/3206>
2022-04-22 13:34:58 +02:00
b8d78743f7 Upgrade platform-tools (33.0.1) for Windows
PR #3206 <https://github.com/Genymobile/scrcpy/pull/3206>
2022-04-22 13:34:11 +02:00
6a4a4a283d Remove obsolete alternative injection method
The previous commit replaced the IInterface instance (the "input"
service) by the InputManager instance (retrieved by
InputManager.getInstance()).

Both define an "injectInputEvent" method, but the alternate version
(probably) does not concern the InputManager.

This reverts commit b7a06278fe.

PR #3190 <https://github.com/Genymobile/scrcpy/pull/3190>
2022-04-22 09:52:41 +02:00
7d8b72d4a6 Adapt event injection to Android 13
Using the "input" service results in a permission error in Android 13.

Use the InputManager instance (retrieved by InputManager.getInstance())
instead.

Fixes #3186 <https://github.com/Genymobile/scrcpy/issues/3186>
PR #3190 <https://github.com/Genymobile/scrcpy/pull/3190>
2022-04-22 09:52:41 +02:00
fa5b2a29e9 Add missing SC_ prefix to header guards 2022-04-12 23:59:01 +02:00
0c94887075 Add missing include
Refs c3d45c8397
2022-04-12 23:51:05 +02:00
88543cb545 Fix icon path in ./run
The data/ directory has been moved to app/data/.

Refs 36c75e15b8
2022-03-30 14:00:05 +02:00
aaf3869a54 Fix OpenGL ES prefix skip 2022-03-30 12:01:01 +02:00
c3d45c8397 Consider emulators as TCP/IP devices
Emulators were wrongly considered as USB devices, so they were selected
using -d instead of -e (which was inconsistent with the adb behavior).

Refs #3005 <https://github.com/Genymobile/scrcpy/issues/3005>
Refs #3137 <https://github.com/Genymobile/scrcpy/issues/3137>
2022-03-22 21:08:08 +01:00
e56f2ac7a9 Log an error on unexpected device state
Refs #3129 <https://github.com/Genymobile/scrcpy/issues/3129>
2022-03-20 14:56:52 +01:00
4ce7af42c6 Use $ANDROID_SERIAL if no selector is specified
Like adb, read the ANDROID_SERIAL environment variable to select a
device by serial if no explicit selection (-s, -d, -e or --tcpip=<addr>)
is provided via the command line.

Fixes #3111 <https://github.com/Genymobile/scrcpy/issues/3111>
PR #3113 <https://github.com/Genymobile/scrcpy/pull/3113>
2022-03-15 08:32:34 +01:00
b1dbc30072 Document exit status in --help
Refs #3085 <https://github.com/Genymobile/scrcpy/pull/3085>
2022-03-10 09:13:21 +01:00
29 changed files with 166 additions and 80 deletions

View File

@ -448,6 +448,9 @@ scrcpy --serial 0123456789abcdef
scrcpy -s 0123456789abcdef # short version scrcpy -s 0123456789abcdef # short version
``` ```
The serial may also be provided via the environment variable `ANDROID_SERIAL`
(also used by `adb`).
If the device is connected over TCP/IP: If the device is connected over TCP/IP:
```bash ```bash

View File

@ -143,12 +143,12 @@ else
prebuilt_libusb = meson.get_cross_property('prebuilt_libusb') prebuilt_libusb = meson.get_cross_property('prebuilt_libusb')
prebuilt_libusb_root = meson.get_cross_property('prebuilt_libusb_root') prebuilt_libusb_root = meson.get_cross_property('prebuilt_libusb_root')
libusb_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_libusb + '/dll' libusb_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_libusb
libusb_include_dir = 'prebuilt-deps/data/' + prebuilt_libusb_root + '/include' libusb_include_dir = 'prebuilt-deps/data/' + prebuilt_libusb_root + '/include'
libusb = declare_dependency( libusb = declare_dependency(
dependencies: [ dependencies: [
cc.find_library('libusb-1.0', dirs: libusb_bin_dir), cc.find_library('msys-usb-1.0', dirs: libusb_bin_dir),
], ],
include_directories: include_directories(libusb_include_dir) include_directories: include_directories(libusb_include_dir)
) )

View File

@ -6,10 +6,10 @@ cd "$DIR"
mkdir -p "$PREBUILT_DATA_DIR" mkdir -p "$PREBUILT_DATA_DIR"
cd "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR"
DEP_DIR=platform-tools-31.0.3 DEP_DIR=platform-tools-33.0.1
FILENAME=platform-tools_r31.0.3-windows.zip FILENAME=platform-tools_r33.0.1-windows.zip
SHA256SUM=0f4b8fdd26af2c3733539d6eebb3c2ed499ea1d4bb1f4e0ecc2d6016961a6e24 SHA256SUM=c1f02d42ea24ef4ff2a405ae7370e764ef4546f9b3e4520f5571a00ed5012c42
if [[ -d "$DEP_DIR" ]] if [[ -d "$DEP_DIR" ]]
then then

View File

@ -6,10 +6,10 @@ cd "$DIR"
mkdir -p "$PREBUILT_DATA_DIR" mkdir -p "$PREBUILT_DATA_DIR"
cd "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR"
DEP_DIR=libusb-1.0.25 DEP_DIR=libusb-1.0.26
FILENAME=libusb-1.0.25.7z FILENAME=libusb-1.0.26-binaries.7z
SHA256SUM=3d1c98416f454026034b2b5d67f8a294053898cb70a8b489874e75b136c6674d SHA256SUM=9c242696342dbde9cdc47239391f71833939bf9f7aa2bbb28cdaabe890465ec5
if [[ -d "$DEP_DIR" ]] if [[ -d "$DEP_DIR" ]]
then then
@ -17,12 +17,18 @@ then
exit 0 exit 0
fi fi
get_file "https://github.com/libusb/libusb/releases/download/v1.0.25/$FILENAME" "$FILENAME" "$SHA256SUM" get_file "https://github.com/libusb/libusb/releases/download/v1.0.26/$FILENAME" "$FILENAME" "$SHA256SUM"
mkdir "$DEP_DIR" mkdir "$DEP_DIR"
cd "$DEP_DIR" cd "$DEP_DIR"
# include/ is the same in all folders of the archive
7z x "../$FILENAME" \ 7z x "../$FILENAME" \
MinGW32/dll/libusb-1.0.dll \ libusb-1.0.26-binaries/libusb-MinGW-Win32/bin/msys-usb-1.0.dll \
MinGW64/dll/libusb-1.0.dll \ libusb-1.0.26-binaries/libusb-MinGW-x64/bin/msys-usb-1.0.dll \
include / libusb-1.0.26-binaries/libusb-MinGW-x64/include/
mv libusb-1.0.26-binaries/libusb-MinGW-Win32/bin MinGW-Win32
mv libusb-1.0.26-binaries/libusb-MinGW-x64/bin MinGW-x64
mv libusb-1.0.26-binaries/libusb-MinGW-x64/include .
rm -rf libusb-1.0.26-binaries

View File

@ -477,6 +477,10 @@ Push file to device (see \fB\-\-push\-target\fR)
.B ADB .B ADB
Path to adb. Path to adb.
.TP
.B ANDROID_SERIAL
Device serial to use if no selector (-s, -d, -e or --tcpip=<addr>) is specified.
.TP .TP
.B SCRCPY_ICON_PATH .B SCRCPY_ICON_PATH
Path to the program icon. Path to the program icon.

View File

@ -473,9 +473,12 @@ sc_adb_accept_device(const struct sc_adb_device *device,
} }
return !strcmp(selector->serial, device->serial); return !strcmp(selector->serial, device->serial);
case SC_ADB_DEVICE_SELECT_USB: case SC_ADB_DEVICE_SELECT_USB:
return !sc_adb_is_serial_tcpip(device->serial); return sc_adb_device_get_type(device->serial) ==
SC_ADB_DEVICE_TYPE_USB;
case SC_ADB_DEVICE_SELECT_TCPIP: case SC_ADB_DEVICE_SELECT_TCPIP:
return sc_adb_is_serial_tcpip(device->serial); // Both emulators and TCP/IP devices are selected via -e
return sc_adb_device_get_type(device->serial) !=
SC_ADB_DEVICE_TYPE_USB;
default: default:
assert(!"Missing SC_ADB_DEVICE_SELECT_* handling"); assert(!"Missing SC_ADB_DEVICE_SELECT_* handling");
break; break;
@ -509,8 +512,10 @@ sc_adb_devices_log(enum sc_log_level level, struct sc_adb_device *devices,
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
struct sc_adb_device *d = &devices[i]; struct sc_adb_device *d = &devices[i];
const char *selection = d->selected ? "-->" : " "; const char *selection = d->selected ? "-->" : " ";
const char *type = sc_adb_is_serial_tcpip(d->serial) ? "(tcpip)" bool is_usb =
: " (usb)"; sc_adb_device_get_type(d->serial) == SC_ADB_DEVICE_TYPE_USB;
const char *type = is_usb ? " (usb)"
: "(tcpip)";
LOG(level, " %s %s %-20s %16s %s", LOG(level, " %s %s %-20s %16s %s",
selection, type, d->serial, d->state, d->model ? d->model : ""); selection, type, d->serial, d->state, d->model ? d->model : "");
} }
@ -531,6 +536,8 @@ sc_adb_device_check_state(struct sc_adb_device *device,
LOGE("A popup should open on the device to request authorization."); LOGE("A popup should open on the device to request authorization.");
LOGE("Check the FAQ: " LOGE("Check the FAQ: "
"<https://github.com/Genymobile/scrcpy/blob/master/FAQ.md>"); "<https://github.com/Genymobile/scrcpy/blob/master/FAQ.md>");
} else {
LOGE("Device could not be connected (state=%s)", state);
} }
return false; return false;
@ -705,8 +712,3 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) {
return sc_adb_parse_device_ip_from_output(buf); return sc_adb_parse_device_ip_from_output(buf);
} }
bool
sc_adb_is_serial_tcpip(const char *serial) {
return strchr(serial, ':');
}

View File

@ -114,13 +114,4 @@ sc_adb_getprop(struct sc_intr *intr, const char *serial, const char *prop,
char * char *
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags); sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
/**
* Indicate if the serial represents an IP address
*
* In practice, it just returns true if and only if it contains a ':', which is
* sufficient to distinguish an ip:port from a real USB serial.
*/
bool
sc_adb_is_serial_tcpip(const char *serial);
#endif #endif

View File

@ -1,6 +1,7 @@
#include "adb_device.h" #include "adb_device.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
void void
sc_adb_device_destroy(struct sc_adb_device *device) { sc_adb_device_destroy(struct sc_adb_device *device) {
@ -25,3 +26,18 @@ sc_adb_devices_destroy(struct sc_vec_adb_devices *devices) {
sc_vector_destroy(devices); sc_vector_destroy(devices);
} }
enum sc_adb_device_type
sc_adb_device_get_type(const char *serial) {
// Starts with "emulator-"
if (!strncmp(serial, "emulator-", sizeof("emulator-") - 1)) {
return SC_ADB_DEVICE_TYPE_EMULATOR;
}
// If the serial contains a ':', then it is a TCP/IP device (it is
// sufficient to distinguish an ip:port from a real USB serial)
if (strchr(serial, ':')) {
return SC_ADB_DEVICE_TYPE_TCPIP;
}
return SC_ADB_DEVICE_TYPE_USB;
}

View File

@ -15,6 +15,12 @@ struct sc_adb_device {
bool selected; bool selected;
}; };
enum sc_adb_device_type {
SC_ADB_DEVICE_TYPE_USB,
SC_ADB_DEVICE_TYPE_TCPIP,
SC_ADB_DEVICE_TYPE_EMULATOR,
};
struct sc_vec_adb_devices SC_VECTOR(struct sc_adb_device); struct sc_vec_adb_devices SC_VECTOR(struct sc_adb_device);
void void
@ -35,4 +41,10 @@ sc_adb_device_move(struct sc_adb_device *dst, struct sc_adb_device *src);
void void
sc_adb_devices_destroy(struct sc_vec_adb_devices *devices); sc_adb_devices_destroy(struct sc_vec_adb_devices *devices);
/**
* Deduce the device type from the serial
*/
enum sc_adb_device_type
sc_adb_device_get_type(const char *serial);
#endif #endif

View File

@ -80,6 +80,11 @@ struct sc_envvar {
const char *text; const char *text;
}; };
struct sc_exit_status {
unsigned value;
const char *text;
};
struct sc_getopt_adapter { struct sc_getopt_adapter {
char *optstring; char *optstring;
struct option *longopts; struct option *longopts;
@ -655,6 +660,11 @@ static const struct sc_envvar envvars[] = {
.name = "ADB", .name = "ADB",
.text = "Path to adb executable", .text = "Path to adb executable",
}, },
{
.name = "ANDROID_SERIAL",
.text = "Device serial to use if no selector (-s, -d, -e or "
"--tcpip=<addr>) is specified",
},
{ {
.name = "SCRCPY_ICON_PATH", .name = "SCRCPY_ICON_PATH",
.text = "Path to the program icon", .text = "Path to the program icon",
@ -662,7 +672,22 @@ static const struct sc_envvar envvars[] = {
{ {
.name = "SCRCPY_SERVER_PATH", .name = "SCRCPY_SERVER_PATH",
.text = "Path to the server binary", .text = "Path to the server binary",
} },
};
static const struct sc_exit_status exit_statuses[] = {
{
.value = 0,
.text = "Normal program termination",
},
{
.value = 1,
.text = "Start failure",
},
{
.value = 2,
.text = "Device disconnected while running",
},
}; };
static char * static char *
@ -901,6 +926,25 @@ print_envvar(const struct sc_envvar *envvar, unsigned cols) {
free(text); free(text);
} }
static void
print_exit_status(const struct sc_exit_status *status, unsigned cols) {
assert(cols > 8); // sc_str_wrap_lines() requires indent < columns
assert(status->text);
// The text starts at 9: 4 ident spaces, 3 chars for numeric value, 2 spaces
char *text = sc_str_wrap_lines(status->text, cols, 9);
if (!text) {
printf("<ERROR>\n");
return;
}
assert(strlen(text) >= 9); // Contains at least the initial identation
// text + 9 to remove the initial indentation
printf(" %3d %s\n", status->value, text + 9);
free(text);
}
void void
scrcpy_print_usage(const char *arg0) { scrcpy_print_usage(const char *arg0) {
#define SC_TERM_COLS_DEFAULT 80 #define SC_TERM_COLS_DEFAULT 80
@ -939,6 +983,11 @@ scrcpy_print_usage(const char *arg0) {
for (size_t i = 0; i < ARRAY_LEN(envvars); ++i) { for (size_t i = 0; i < ARRAY_LEN(envvars); ++i) {
print_envvar(&envvars[i], cols); print_envvar(&envvars[i], cols);
} }
printf("\nExit status:\n\n");
for (size_t i = 0; i < ARRAY_LEN(exit_statuses); ++i) {
print_exit_status(&exit_statuses[i], cols);
}
} }
static bool static bool

View File

@ -1,5 +1,5 @@
#ifndef COMMON_H #ifndef SC_COMMON_H
#define COMMON_H #define SC_COMMON_H
#include "config.h" #include "config.h"
#include "compat.h" #include "compat.h"

View File

@ -1,5 +1,5 @@
#ifndef COMPAT_H #ifndef SC_COMPAT_H
#define COMPAT_H #define SC_COMPAT_H
#include "config.h" #include "config.h"

View File

@ -1,5 +1,5 @@
#ifndef CONTROLMSG_H #ifndef SC_CONTROLMSG_H
#define CONTROLMSG_H #define SC_CONTROLMSG_H
#include "common.h" #include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef CONTROLLER_H #ifndef SC_CONTROLLER_H
#define CONTROLLER_H #define SC_CONTROLLER_H
#include "common.h" #include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef DEVICEMSG_H #ifndef SC_DEVICEMSG_H
#define DEVICEMSG_H #define SC_DEVICEMSG_H
#include "common.h" #include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef FPSCOUNTER_H #ifndef SC_FPSCOUNTER_H
#define FPSCOUNTER_H #define SC_FPSCOUNTER_H
#include "common.h" #include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef ICON_H #ifndef SC_ICON_H
#define ICON_H #define SC_ICON_H
#include "common.h" #include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef INPUTMANAGER_H #ifndef SC_INPUTMANAGER_H
#define INPUTMANAGER_H #define SC_INPUTMANAGER_H
#include "common.h" #include "common.h"

View File

@ -28,7 +28,7 @@ sc_opengl_init(struct sc_opengl *gl) {
sizeof(OPENGL_ES_PREFIX) - 1); sizeof(OPENGL_ES_PREFIX) - 1);
if (gl->is_opengles) { if (gl->is_opengles) {
/* skip the prefix */ /* skip the prefix */
version += sizeof(PREFIX) - 1; version += sizeof(OPENGL_ES_PREFIX) - 1;
} }
int r = sscanf(version, "%d.%d", &gl->version_major, &gl->version_minor); int r = sscanf(version, "%d.%d", &gl->version_major, &gl->version_minor);

View File

@ -1,5 +1,5 @@
#ifndef RECEIVER_H #ifndef SC_RECEIVER_H
#define RECEIVER_H #define SC_RECEIVER_H
#include "common.h" #include "common.h"

View File

@ -649,7 +649,8 @@ sc_server_configure_tcpip_known_address(struct sc_server *server,
static bool static bool
sc_server_configure_tcpip_unknown_address(struct sc_server *server, sc_server_configure_tcpip_unknown_address(struct sc_server *server,
const char *serial) { const char *serial) {
bool is_already_tcpip = sc_adb_is_serial_tcpip(serial); bool is_already_tcpip =
sc_adb_device_get_type(serial) == SC_ADB_DEVICE_TYPE_TCPIP;
if (is_already_tcpip) { if (is_already_tcpip) {
// Nothing to do // Nothing to do
LOGI("Device already connected via TCP/IP: %s", serial); LOGI("Device already connected via TCP/IP: %s", serial);
@ -707,7 +708,15 @@ run_server(void *data) {
} else if (params->select_tcpip) { } else if (params->select_tcpip) {
selector.type = SC_ADB_DEVICE_SELECT_TCPIP; selector.type = SC_ADB_DEVICE_SELECT_TCPIP;
} else { } else {
selector.type = SC_ADB_DEVICE_SELECT_ALL; // No explicit selection, check $ANDROID_SERIAL
const char *env_serial = getenv("ANDROID_SERIAL");
if (env_serial) {
LOGI("Using ANDROID_SERIAL: %s", env_serial);
selector.type = SC_ADB_DEVICE_SELECT_SERIAL;
selector.serial = env_serial;
} else {
selector.type = SC_ADB_DEVICE_SELECT_ALL;
}
} }
struct sc_adb_device device; struct sc_adb_device device;
ok = sc_adb_select_device(&server->intr, &selector, 0, &device); ok = sc_adb_select_device(&server->intr, &selector, 0, &device);

View File

@ -1,6 +1,6 @@
// generic circular buffer (bounded queue) implementation // generic circular buffer (bounded queue) implementation
#ifndef CBUF_H #ifndef SC_CBUF_H
#define CBUF_H #define SC_CBUF_H
#include "common.h" #include "common.h"

View File

@ -1,5 +1,5 @@
#ifndef NET_H #ifndef SC_NET_H
#define NET_H #define SC_NET_H
#include "common.h" #include "common.h"

View File

@ -21,5 +21,5 @@ ffmpeg_avformat = 'avformat-58'
ffmpeg_avutil = 'avutil-56' ffmpeg_avutil = 'avutil-56'
prebuilt_ffmpeg = 'ffmpeg-win32-4.3.1' prebuilt_ffmpeg = 'ffmpeg-win32-4.3.1'
prebuilt_sdl2 = 'SDL2-2.0.20/i686-w64-mingw32' prebuilt_sdl2 = 'SDL2-2.0.20/i686-w64-mingw32'
prebuilt_libusb_root = 'libusb-1.0.25' prebuilt_libusb_root = 'libusb-1.0.26'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW32' prebuilt_libusb = prebuilt_libusb_root + '/MinGW-Win32'

View File

@ -21,5 +21,5 @@ ffmpeg_avformat = 'avformat-59'
ffmpeg_avutil = 'avutil-57' ffmpeg_avutil = 'avutil-57'
prebuilt_ffmpeg = 'ffmpeg-win64-5.0' prebuilt_ffmpeg = 'ffmpeg-win64-5.0'
prebuilt_sdl2 = 'SDL2-2.0.20/x86_64-w64-mingw32' prebuilt_sdl2 = 'SDL2-2.0.20/x86_64-w64-mingw32'
prebuilt_libusb_root = 'libusb-1.0.25' prebuilt_libusb_root = 'libusb-1.0.26'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW64' prebuilt_libusb = prebuilt_libusb_root + '/MinGW-x64'

View File

@ -75,12 +75,10 @@ prepare-deps-win64:
@app/prebuilt-deps/prepare-libusb.sh @app/prebuilt-deps/prepare-libusb.sh
build-win32: prepare-deps-win32 build-win32: prepare-deps-win32
# -Dusb=false because of libusb-win32 build issue, cf #3011
[ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \ [ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \
meson "$(WIN32_BUILD_DIR)" \ meson "$(WIN32_BUILD_DIR)" \
--cross-file cross_win32.txt \ --cross-file cross_win32.txt \
--buildtype release --strip -Db_lto=true \ --buildtype release --strip -Db_lto=true \
-Dusb=false \
-Dcompile_server=false \ -Dcompile_server=false \
-Dportable=true ) -Dportable=true )
ninja -C "$(WIN32_BUILD_DIR)" ninja -C "$(WIN32_BUILD_DIR)"
@ -111,7 +109,7 @@ dist-win32: build-server build-win32
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
#cp app/prebuilt-deps/data/libusb-1.0.25/MinGW32/dll/libusb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/libusb-1.0.26/MinGW-Win32/msys-usb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
dist-win64: build-server build-win64 dist-win64: build-server build-win64
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)" mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
@ -130,7 +128,7 @@ dist-win64: build-server build-win64
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.0.20/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/SDL2-2.0.20/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/libusb-1.0.25/MinGW64/dll/libusb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp app/prebuilt-deps/data/libusb-1.0.26/MinGW-x64/msys-usb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
zip-win32: dist-win32 zip-win32: dist-win32
cd "$(DIST)/$(WIN32_TARGET_DIR)"; \ cd "$(DIST)/$(WIN32_TARGET_DIR)"; \

2
run
View File

@ -20,6 +20,6 @@ then
exit 1 exit 1
fi fi
SCRCPY_ICON_PATH="data/icon.png" \ SCRCPY_ICON_PATH="app/data/icon.png" \
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" \ SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" \
"$BUILDDIR/app/scrcpy" "$@" "$BUILDDIR/app/scrcpy" "$@"

View File

@ -2,7 +2,6 @@ package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.Ln; import com.genymobile.scrcpy.Ln;
import android.os.IInterface;
import android.view.InputEvent; import android.view.InputEvent;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -14,24 +13,18 @@ public final class InputManager {
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1; public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;
private final IInterface manager; private final android.hardware.input.InputManager manager;
private Method injectInputEventMethod; private Method injectInputEventMethod;
private boolean alternativeInjectInputEventMethod;
private static Method setDisplayIdMethod; private static Method setDisplayIdMethod;
public InputManager(IInterface manager) { public InputManager(android.hardware.input.InputManager manager) {
this.manager = manager; this.manager = manager;
} }
private Method getInjectInputEventMethod() throws NoSuchMethodException { private Method getInjectInputEventMethod() throws NoSuchMethodException {
if (injectInputEventMethod == null) { if (injectInputEventMethod == null) {
try { injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class);
injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class);
} catch (NoSuchMethodException e) {
injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class, int.class);
alternativeInjectInputEventMethod = true;
}
} }
return injectInputEventMethod; return injectInputEventMethod;
} }
@ -39,10 +32,6 @@ public final class InputManager {
public boolean injectInputEvent(InputEvent inputEvent, int mode) { public boolean injectInputEvent(InputEvent inputEvent, int mode) {
try { try {
Method method = getInjectInputEventMethod(); Method method = getInjectInputEventMethod();
if (alternativeInjectInputEventMethod) {
// See <https://github.com/Genymobile/scrcpy/issues/2250>
return (boolean) method.invoke(manager, inputEvent, mode, 0);
}
return (boolean) method.invoke(manager, inputEvent, mode); return (boolean) method.invoke(manager, inputEvent, mode);
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
Ln.e("Could not invoke method", e); Ln.e("Could not invoke method", e);

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.os.IBinder; import android.os.IBinder;
import android.os.IInterface; import android.os.IInterface;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@SuppressLint("PrivateApi,DiscouragedPrivateApi") @SuppressLint("PrivateApi,DiscouragedPrivateApi")
@ -56,7 +57,13 @@ public final class ServiceManager {
public InputManager getInputManager() { public InputManager getInputManager() {
if (inputManager == null) { if (inputManager == null) {
inputManager = new InputManager(getService("input", "android.hardware.input.IInputManager")); try {
Method getInstanceMethod = android.hardware.input.InputManager.class.getDeclaredMethod("getInstance");
android.hardware.input.InputManager im = (android.hardware.input.InputManager) getInstanceMethod.invoke(null);
inputManager = new InputManager(im);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new AssertionError(e);
}
} }
return inputManager; return inputManager;
} }