Merge branch 'dev' into master

This commit is contained in:
Romain Vimont 2019-01-19 21:40:55 +01:00
commit 3aacb7967d
16 changed files with 76 additions and 120 deletions

14
FAQ.md
View file

@ -24,20 +24,6 @@ If you still encounter problems, please see [issue 9].
[issue 9]: https://github.com/Genymobile/scrcpy/issues/9 [issue 9]: https://github.com/Genymobile/scrcpy/issues/9
### I get a black screen for some applications like Silence
This is expected, they requested to [protect] the screen.
In [Silence], you can disable it in settings → Privacy → Screen security.
[protect]: https://developer.android.com/reference/android/view/Display#FLAG_SECURE
[silence]: https://f-droid.org/en/packages/org.smssecure.smssecure/
See [issue 36].
[issue 36]: https://github.com/Genymobile/scrcpy/issues/36
### Mouse clicks do not work ### Mouse clicks do not work
On some devices, you may need to enable an option to allow [simulating input]. On some devices, you may need to enable an option to allow [simulating input].

View file

@ -100,10 +100,10 @@ dist-win32: build-server build-win32 build-win32-noconsole
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN32_TARGET_DIR)/" cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/" cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp "$(WIN32_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/scrcpy-noconsole.exe" cp "$(WIN32_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/scrcpy-noconsole.exe"
cp prebuilt-deps/ffmpeg-4.0.2-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0.2-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0.2-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0.2-win32-shared/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win32-shared/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/" cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
@ -114,10 +114,10 @@ dist-win64: build-server build-win64 build-win64-noconsole
cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN64_TARGET_DIR)/" cp "$(SERVER_BUILD_DIR)"/server/scrcpy-server.jar "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/" cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp "$(WIN64_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/scrcpy-noconsole.exe" cp "$(WIN64_NOCONSOLE_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/scrcpy-noconsole.exe"
cp prebuilt-deps/ffmpeg-4.0.2-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0.2-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0.2-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.0.2-win64-shared/bin/swresample-3.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp prebuilt-deps/ffmpeg-4.1-win64-shared/bin/swresample-3.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/" cp prebuilt-deps/platform-tools/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp prebuilt-deps/platform-tools/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" cp prebuilt-deps/platform-tools/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"

View file

@ -135,11 +135,6 @@ process_t adb_install(const char *serial, const char *local) {
return proc; return proc;
} }
process_t adb_remove_path(const char *serial, const char *path) {
const char *const adb_cmd[] = {"shell", "rm", path};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
}
SDL_bool process_check_success(process_t proc, const char *name) { SDL_bool process_check_success(process_t proc, const char *name) {
if (proc == PROCESS_NONE) { if (proc == PROCESS_NONE) {
LOGE("Could not execute \"%s\"", name); LOGE("Could not execute \"%s\"", name);

View file

@ -49,7 +49,6 @@ process_t adb_reverse(const char *serial, const char *device_socket_name, uint16
process_t adb_reverse_remove(const char *serial, const char *device_socket_name); process_t adb_reverse_remove(const char *serial, const char *device_socket_name);
process_t adb_push(const char *serial, const char *local, const char *remote); process_t adb_push(const char *serial, const char *local, const char *remote);
process_t adb_install(const char *serial, const char *local); process_t adb_install(const char *serial, const char *local);
process_t adb_remove_path(const char *serial, const char *path);
// convenience function to wait for a successful process execution // convenience function to wait for a successful process execution
// automatically log process errors with the provided process name // automatically log process errors with the provided process name

View file

@ -13,8 +13,8 @@ struct size {
}; };
struct point { struct point {
Uint16 x; Sint32 x;
Uint16 y; Sint32 y;
}; };
struct position { struct position {

View file

@ -8,10 +8,10 @@
#include "log.h" #include "log.h"
static void write_position(Uint8 *buf, const struct position *position) { static void write_position(Uint8 *buf, const struct position *position) {
buffer_write16be(&buf[0], position->point.x); buffer_write32be(&buf[0], position->point.x);
buffer_write16be(&buf[2], position->point.y); buffer_write32be(&buf[4], position->point.y);
buffer_write16be(&buf[4], position->screen_size.width); buffer_write16be(&buf[8], position->screen_size.width);
buffer_write16be(&buf[6], position->screen_size.height); buffer_write16be(&buf[10], position->screen_size.height);
} }
int control_event_serialize(const struct control_event *event, unsigned char *buf) { int control_event_serialize(const struct control_event *event, unsigned char *buf) {
@ -37,12 +37,12 @@ int control_event_serialize(const struct control_event *event, unsigned char *bu
buf[1] = event->mouse_event.action; buf[1] = event->mouse_event.action;
buffer_write32be(&buf[2], event->mouse_event.buttons); buffer_write32be(&buf[2], event->mouse_event.buttons);
write_position(&buf[6], &event->mouse_event.position); write_position(&buf[6], &event->mouse_event.position);
return 14; return 18;
case CONTROL_EVENT_TYPE_SCROLL: case CONTROL_EVENT_TYPE_SCROLL:
write_position(&buf[1], &event->scroll_event.position); write_position(&buf[1], &event->scroll_event.position);
buffer_write32be(&buf[9], (Uint32) event->scroll_event.hscroll); buffer_write32be(&buf[13], (Uint32) event->scroll_event.hscroll);
buffer_write32be(&buf[13], (Uint32) event->scroll_event.vscroll); buffer_write32be(&buf[17], (Uint32) event->scroll_event.vscroll);
return 17; return 21;
case CONTROL_EVENT_TYPE_COMMAND: case CONTROL_EVENT_TYPE_COMMAND:
buf[1] = event->command_event.action; buf[1] = event->command_event.action;
return 2; return 2;

View file

@ -18,9 +18,15 @@ static void convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int
*y = (int) (*y / scale_y) - viewport.y; *y = (int) (*y / scale_y) - viewport.y;
} }
static void get_mouse_point(struct screen *screen, int *x, int *y) { static struct point get_mouse_point(struct screen *screen) {
SDL_GetMouseState(x, y); int x;
convert_to_renderer_coordinates(screen->renderer, x, y); int y;
SDL_GetMouseState(&x, &y);
convert_to_renderer_coordinates(screen->renderer, &x, &y);
return (struct point) {
.x = x,
.y = y,
};
} }
static const int ACTION_DOWN = 1; static const int ACTION_DOWN = 1;
@ -273,9 +279,6 @@ static SDL_bool is_outside_device_screen(struct input_manager *input_manager,
void input_manager_process_mouse_button(struct input_manager *input_manager, void input_manager_process_mouse_button(struct input_manager *input_manager,
const SDL_MouseButtonEvent *event) { const SDL_MouseButtonEvent *event) {
SDL_bool outside_device_screen = is_outside_device_screen(input_manager,
event->x,
event->y);
if (event->type == SDL_MOUSEBUTTONDOWN) { if (event->type == SDL_MOUSEBUTTONDOWN) {
if (event->button == SDL_BUTTON_RIGHT) { if (event->button == SDL_BUTTON_RIGHT) {
press_back_or_turn_screen_on(input_manager->controller); press_back_or_turn_screen_on(input_manager->controller);
@ -286,17 +289,16 @@ void input_manager_process_mouse_button(struct input_manager *input_manager,
return; return;
} }
// double-click on black borders resize to fit the device screen // double-click on black borders resize to fit the device screen
if (event->button == SDL_BUTTON_LEFT && event->clicks == 2 if (event->button == SDL_BUTTON_LEFT && event->clicks == 2) {
&& outside_device_screen) { SDL_bool outside= is_outside_device_screen(input_manager,
event->x,
event->y);
if (outside) {
screen_resize_to_fit(input_manager->screen); screen_resize_to_fit(input_manager->screen);
return; return;
} }
// otherwise, send the click event to the device
} }
// otherwise, send the click event to the device
if (outside_device_screen) {
// ignore
return;
} }
struct control_event control_event; struct control_event control_event;
@ -309,22 +311,9 @@ void input_manager_process_mouse_button(struct input_manager *input_manager,
void input_manager_process_mouse_wheel(struct input_manager *input_manager, void input_manager_process_mouse_wheel(struct input_manager *input_manager,
const SDL_MouseWheelEvent *event) { const SDL_MouseWheelEvent *event) {
int x;
int y;
get_mouse_point(input_manager->screen, &x, &y);
if (is_outside_device_screen(input_manager, x, y)) {
// ignore
return;
}
SDL_assert_release(x >= 0 && x < 0x10000 && y >= 0 && y < 0x10000);
struct position position = { struct position position = {
.screen_size = input_manager->screen->frame_size, .screen_size = input_manager->screen->frame_size,
.point = { .point = get_mouse_point(input_manager->screen),
.x = (Uint16) x,
.y = (Uint16) y,
},
}; };
struct control_event control_event; struct control_event control_event;
if (mouse_wheel_from_sdl_to_android(event, position, &control_event)) { if (mouse_wheel_from_sdl_to_android(event, position, &control_event)) {

View file

@ -30,6 +30,9 @@ SDL_bool sdl_init_and_configure(void) {
} }
#endif #endif
// Do not disable the screensaver when scrcpy is running
SDL_EnableScreenSaver();
return SDL_TRUE; return SDL_TRUE;
} }

View file

@ -34,11 +34,6 @@ static SDL_bool push_server(const char *serial) {
return process_check_success(process, "adb push"); return process_check_success(process, "adb push");
} }
static SDL_bool remove_server(const char *serial) {
process_t process = adb_remove_path(serial, DEVICE_SERVER_PATH);
return process_check_success(process, "adb shell rm");
}
static SDL_bool enable_tunnel_reverse(const char *serial, Uint16 local_port) { static SDL_bool enable_tunnel_reverse(const char *serial, Uint16 local_port) {
process_t process = adb_reverse(serial, SOCKET_NAME, local_port); process_t process = adb_reverse(serial, SOCKET_NAME, local_port);
return process_check_success(process, "adb reverse"); return process_check_success(process, "adb reverse");
@ -93,7 +88,7 @@ static process_t execute_server(const char *serial,
max_size_string, max_size_string,
bit_rate_string, bit_rate_string,
tunnel_forward ? "true" : "false", tunnel_forward ? "true" : "false",
crop ? crop : "''", crop ? crop : "-",
send_frame_meta ? "true" : "false", send_frame_meta ? "true" : "false",
}; };
return adb_execute(serial, cmd, sizeof(cmd) / sizeof(cmd[0])); return adb_execute(serial, cmd, sizeof(cmd) / sizeof(cmd[0]));
@ -167,8 +162,6 @@ SDL_bool server_start(struct server *server, const char *serial,
return SDL_FALSE; return SDL_FALSE;
} }
server->server_copied_to_device = SDL_TRUE;
if (!enable_tunnel(server)) { if (!enable_tunnel(server)) {
SDL_free((void *) server->serial); SDL_free((void *) server->serial);
return SDL_FALSE; return SDL_FALSE;
@ -229,10 +222,6 @@ socket_t server_connect_to(struct server *server) {
close_socket(&server->server_socket); close_socket(&server->server_socket);
} }
// the server is started, we can clean up the jar from the temporary folder
remove_server(server->serial); // ignore failure
server->server_copied_to_device = SDL_FALSE;
// we don't need the adb tunnel anymore // we don't need the adb tunnel anymore
disable_tunnel(server); // ignore failure disable_tunnel(server); // ignore failure
server->tunnel_enabled = SDL_FALSE; server->tunnel_enabled = SDL_FALSE;
@ -254,10 +243,6 @@ void server_stop(struct server *server) {
// ignore failure // ignore failure
disable_tunnel(server); disable_tunnel(server);
} }
if (server->server_copied_to_device) {
remove_server(server->serial); // ignore failure
}
} }
void server_destroy(struct server *server) { void server_destroy(struct server *server) {

View file

@ -13,7 +13,6 @@ struct server {
SDL_bool tunnel_enabled; SDL_bool tunnel_enabled;
SDL_bool tunnel_forward; // use "adb forward" instead of "adb reverse" SDL_bool tunnel_forward; // use "adb forward" instead of "adb reverse"
SDL_bool send_frame_meta; // request frame PTS to be able to record properly SDL_bool send_frame_meta; // request frame PTS to be able to record properly
SDL_bool server_copied_to_device;
}; };
#define SERVER_INITIALIZER { \ #define SERVER_INITIALIZER { \
@ -25,7 +24,6 @@ struct server {
.tunnel_enabled = SDL_FALSE, \ .tunnel_enabled = SDL_FALSE, \
.tunnel_forward = SDL_FALSE, \ .tunnel_forward = SDL_FALSE, \
.send_frame_meta = SDL_FALSE, \ .send_frame_meta = SDL_FALSE, \
.server_copied_to_device = SDL_FALSE, \
} }
// init default values // init default values

View file

@ -15,6 +15,6 @@ cpu = 'i686'
endian = 'little' endian = 'little'
[properties] [properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.0.2-win32-shared' prebuilt_ffmpeg_shared = 'ffmpeg-4.1-win32-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.0.2-win32-dev' prebuilt_ffmpeg_dev = 'ffmpeg-4.1-win32-dev'
prebuilt_sdl2 = 'SDL2-2.0.9/i686-w64-mingw32' prebuilt_sdl2 = 'SDL2-2.0.9/i686-w64-mingw32'

View file

@ -15,6 +15,6 @@ cpu = 'x86_64'
endian = 'little' endian = 'little'
[properties] [properties]
prebuilt_ffmpeg_shared = 'ffmpeg-4.0.2-win64-shared' prebuilt_ffmpeg_shared = 'ffmpeg-4.1-win64-shared'
prebuilt_ffmpeg_dev = 'ffmpeg-4.0.2-win64-dev' prebuilt_ffmpeg_dev = 'ffmpeg-4.1-win64-dev'
prebuilt_sdl2 = 'SDL2-2.0.9/x86_64-w64-mingw32' prebuilt_sdl2 = 'SDL2-2.0.9/x86_64-w64-mingw32'

View file

@ -10,24 +10,24 @@ prepare-win32: prepare-sdl2 prepare-ffmpeg-shared-win32 prepare-ffmpeg-dev-win32
prepare-win64: prepare-sdl2 prepare-ffmpeg-shared-win64 prepare-ffmpeg-dev-win64 prepare-adb prepare-win64: prepare-sdl2 prepare-ffmpeg-shared-win64 prepare-ffmpeg-dev-win64 prepare-adb
prepare-ffmpeg-shared-win32: prepare-ffmpeg-shared-win32:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-4.0.2-win32-shared.zip \ @./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-4.1-win32-shared.zip \
cc190a3a4cf7bfbd4fbaa92609c1501a1de458055e6cfea8b745c1d515013aa8 \ e692b18c01745d262c03294b382fd64df68fabe3c66aa4546a3ad3935175cde3 \
ffmpeg-4.0.2-win32-shared ffmpeg-4.1-win32-shared
prepare-ffmpeg-dev-win32: prepare-ffmpeg-dev-win32:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-4.0.2-win32-dev.zip \ @./prepare-dep https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-4.1-win32-dev.zip \
c72c74bad74ac0541f1b43090c26a50017c49041c182a703abd2057bb8cdc238 \ 34bc5e471fb9160609abd6bc271e361050f3ff7376b1b8a0873cca02b38277c8 \
ffmpeg-4.0.2-win32-dev ffmpeg-4.1-win32-dev
prepare-ffmpeg-shared-win64: prepare-ffmpeg-shared-win64:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-4.0.2-win64-shared.zip \ @./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-4.1-win64-shared.zip \
ede566aca8b5348dff85570f9638c6bad33209f9419f79db7bde7daa37599bff \ c4908c97436c946509dc365e421159274fa4b1e66dce6fb5b63d82a6294d5357 \
ffmpeg-4.0.2-win64-shared ffmpeg-4.1-win64-shared
prepare-ffmpeg-dev-win64: prepare-ffmpeg-dev-win64:
@./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.0.2-win64-dev.zip \ @./prepare-dep https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-4.1-win64-dev.zip \
23ee994161c51285cb956b98d3caa499d48083dae7b26c1fdf77f22e98df1c5f \ 761ec79aa3dae66698c9791a2f0bb9da8794246f8356cadc741ddc0eabab0471 \
ffmpeg-4.0.2-win64-dev ffmpeg-4.1-win64-dev
prepare-sdl2: prepare-sdl2:
@./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.9-mingw.tar.gz \ @./prepare-dep https://libsdl.org/release/SDL2-devel-2.0.9-mingw.tar.gz \

View file

@ -132,8 +132,8 @@ public class ControlEventReader {
} }
private static Position readPosition(ByteBuffer buffer) { private static Position readPosition(ByteBuffer buffer) {
int x = toUnsigned(buffer.getShort()); int x = buffer.getInt();
int y = toUnsigned(buffer.getShort()); int y = buffer.getInt();
int screenWidth = toUnsigned(buffer.getShort()); int screenWidth = toUnsigned(buffer.getShort());
int screenHeight = toUnsigned(buffer.getShort()); int screenHeight = toUnsigned(buffer.getShort());
return new Position(x, y, screenWidth, screenHeight); return new Position(x, y, screenWidth, screenHeight);

View file

@ -151,7 +151,7 @@ public class ScreenEncoder implements Device.RotationListener {
} }
private static IBinder createDisplay() { private static IBinder createDisplay() {
return SurfaceControl.createDisplay("scrcpy", false); return SurfaceControl.createDisplay("scrcpy", true);
} }
private static void configure(MediaCodec codec, MediaFormat format) { private static void configure(MediaCodec codec, MediaFormat format) {

View file

@ -2,11 +2,14 @@ package com.genymobile.scrcpy;
import android.graphics.Rect; import android.graphics.Rect;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
public final class Server { public final class Server {
private static final String SERVER_PATH = "/data/local/tmp/scrcpy-server.jar";
private Server() { private Server() {
// not instantiable // not instantiable
} }
@ -46,35 +49,24 @@ public final class Server {
@SuppressWarnings("checkstyle:MagicNumber") @SuppressWarnings("checkstyle:MagicNumber")
private static Options createOptions(String... args) { private static Options createOptions(String... args) {
if (args.length != 5)
throw new IllegalArgumentException("Expecting 5 parameters");
Options options = new Options(); Options options = new Options();
if (args.length < 1) {
return options;
}
int maxSize = Integer.parseInt(args[0]) & ~7; // multiple of 8 int maxSize = Integer.parseInt(args[0]) & ~7; // multiple of 8
options.setMaxSize(maxSize); options.setMaxSize(maxSize);
if (args.length < 2) {
return options;
}
int bitRate = Integer.parseInt(args[1]); int bitRate = Integer.parseInt(args[1]);
options.setBitRate(bitRate); options.setBitRate(bitRate);
if (args.length < 3) {
return options;
}
// use "adb forward" instead of "adb tunnel"? (so the server must listen) // use "adb forward" instead of "adb tunnel"? (so the server must listen)
boolean tunnelForward = Boolean.parseBoolean(args[2]); boolean tunnelForward = Boolean.parseBoolean(args[2]);
options.setTunnelForward(tunnelForward); options.setTunnelForward(tunnelForward);
if (args.length < 4) {
return options;
}
Rect crop = parseCrop(args[3]); Rect crop = parseCrop(args[3]);
options.setCrop(crop); options.setCrop(crop);
if (args.length < 5) {
return options;
}
boolean sendFrameMeta = Boolean.parseBoolean(args[4]); boolean sendFrameMeta = Boolean.parseBoolean(args[4]);
options.setSendFrameMeta(sendFrameMeta); options.setSendFrameMeta(sendFrameMeta);
@ -82,7 +74,7 @@ public final class Server {
} }
private static Rect parseCrop(String crop) { private static Rect parseCrop(String crop) {
if (crop.isEmpty()) { if ("-".equals(crop)) {
return null; return null;
} }
// input format: "width:height:x:y" // input format: "width:height:x:y"
@ -97,6 +89,14 @@ public final class Server {
return new Rect(x, y, x + width, y + height); return new Rect(x, y, x + width, y + height);
} }
private static void unlinkSelf() {
try {
new File(SERVER_PATH).delete();
} catch (Exception e) {
Ln.e("Cannot unlink server", e);
}
}
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override @Override
@ -105,6 +105,7 @@ public final class Server {
} }
}); });
unlinkSelf();
Options options = createOptions(args); Options options = createOptions(args);
scrcpy(options); scrcpy(options);
} }