From df017160ed9a9856c3a8eb08de29d77c14df70f0 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Jun 2021 12:33:05 +0200 Subject: [PATCH 1/9] Replace strcpy() by memcpy() It was safe to call strcpy() since the input length was checked, but then it is more straightforward to call memcpy() directly. --- app/src/scrcpy.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 179021563b..4dcb412fca 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -216,14 +216,15 @@ av_log_callback(void *avcl, int level, const char *fmt, va_list vl) { if (priority == 0) { return; } - char *local_fmt = malloc(strlen(fmt) + 10); + + size_t fmt_len = strlen(fmt); + char *local_fmt = malloc(fmt_len + 10); if (!local_fmt) { LOGC("Could not allocate string"); return; } - // strcpy is safe here, the destination is large enough - strcpy(local_fmt, "[FFmpeg] "); - strcpy(local_fmt + 9, fmt); + memcpy(local_fmt, "[FFmpeg] ", 9); // do not write the final '\0' + memcpy(local_fmt + 9, fmt, fmt_len + 1); // include '\0' SDL_LogMessageV(SDL_LOG_CATEGORY_VIDEO, priority, local_fmt, vl); free(local_fmt); } From 8b90e1d3f46b77e162caa29a89952182edaa465c Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Jun 2021 00:32:55 +0200 Subject: [PATCH 2/9] Remove extra ';' in #define --- app/src/control_msg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/control_msg.h b/app/src/control_msg.h index c1099c794f..a259d0db42 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -17,8 +17,8 @@ // type: 1 byte; paste flag: 1 byte; length: 4 bytes #define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6) -#define POINTER_ID_MOUSE UINT64_C(-1); -#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2); +#define POINTER_ID_MOUSE UINT64_C(-1) +#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2) enum control_msg_type { CONTROL_MSG_TYPE_INJECT_KEYCODE, From 7db0189f23bc3dd3802c751ed44a1dd367523a5a Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Jun 2021 00:42:55 +0200 Subject: [PATCH 3/9] Forward mouse motion only on main clicks Mouse motion events were forwarded as soon as any mouse button was pressed. Instead, only consider left-click (and also middle-click and right-click if --forward-all-clicks is enabled). --- app/src/input_manager.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/input_manager.c b/app/src/input_manager.c index b008c4db22..a5d0ad07a0 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -595,8 +595,12 @@ convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen, static void input_manager_process_mouse_motion(struct input_manager *im, const SDL_MouseMotionEvent *event) { - if (!event->state) { - // do not send motion events when no button is pressed + uint32_t mask = SDL_BUTTON_LMASK; + if (im->forward_all_clicks) { + mask |= SDL_BUTTON_MMASK | SDL_BUTTON_RMASK; + } + if (!(event->state & mask)) { + // do not send motion events when no click is pressed return; } if (event->which == SDL_TOUCH_MOUSEID) { From 937fa704a6bb07a264e247bb41de08b5378de39e Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Thu, 17 Jun 2021 22:40:30 +0300 Subject: [PATCH 4/9] Add --verbosity=verbose log level PR #2371 Signed-off-by: Romain Vimont --- app/scrcpy.1 | 2 +- app/src/cli.c | 7 ++++++- app/src/main.c | 2 ++ app/src/scrcpy.h | 1 + app/src/server.c | 2 ++ server/src/main/java/com/genymobile/scrcpy/Ln.java | 9 ++++++++- 6 files changed, 20 insertions(+), 3 deletions(-) diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 7b6f1faa69..62dc9677d8 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -193,7 +193,7 @@ It requires to lock the video orientation (see --lock-video-orientation). .TP .BI "\-V, \-\-verbosity " value -Set the log level ("debug", "info", "warn" or "error"). +Set the log level ("verbose", "debug", "info", "warn" or "error"). Default is "info" for release builds, "debug" for debug builds. diff --git a/app/src/cli.c b/app/src/cli.c index 6e1180bc2e..4c1fbb2f3e 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -184,7 +184,7 @@ scrcpy_print_usage(const char *arg0) { "\n" #endif " -V, --verbosity value\n" - " Set the log level (debug, info, warn or error).\n" + " Set the log level (verbose, debug, info, warn or error).\n" #ifndef NDEBUG " Default is debug.\n" #else @@ -505,6 +505,11 @@ parse_display_id(const char *s, uint32_t *display_id) { static bool parse_log_level(const char *s, enum sc_log_level *log_level) { + if (!strcmp(s, "verbose")) { + *log_level = SC_LOG_LEVEL_VERBOSE; + return true; + } + if (!strcmp(s, "debug")) { *log_level = SC_LOG_LEVEL_DEBUG; return true; diff --git a/app/src/main.c b/app/src/main.c index a468aed7f1..c3a7ad2eae 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -41,6 +41,8 @@ print_version(void) { static SDL_LogPriority convert_log_level_to_sdl(enum sc_log_level level) { switch (level) { + case SC_LOG_LEVEL_VERBOSE: + return SDL_LOG_PRIORITY_VERBOSE; case SC_LOG_LEVEL_DEBUG: return SDL_LOG_PRIORITY_DEBUG; case SC_LOG_LEVEL_INFO: diff --git a/app/src/scrcpy.h b/app/src/scrcpy.h index 405dc7f3b6..0a2deb71e2 100644 --- a/app/src/scrcpy.h +++ b/app/src/scrcpy.h @@ -8,6 +8,7 @@ #include enum sc_log_level { + SC_LOG_LEVEL_VERBOSE, SC_LOG_LEVEL_DEBUG, SC_LOG_LEVEL_INFO, SC_LOG_LEVEL_WARN, diff --git a/app/src/server.c b/app/src/server.c index 41e8166c0a..a4cdb0c970 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -235,6 +235,8 @@ enable_tunnel_any_port(struct server *server, struct sc_port_range port_range, static const char * log_level_to_server_string(enum sc_log_level level) { switch (level) { + case SC_LOG_LEVEL_VERBOSE: + return "verbose"; case SC_LOG_LEVEL_DEBUG: return "debug"; case SC_LOG_LEVEL_INFO: diff --git a/server/src/main/java/com/genymobile/scrcpy/Ln.java b/server/src/main/java/com/genymobile/scrcpy/Ln.java index c218fa0fc0..061cda9595 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Ln.java +++ b/server/src/main/java/com/genymobile/scrcpy/Ln.java @@ -12,7 +12,7 @@ public final class Ln { private static final String PREFIX = "[server] "; enum Level { - DEBUG, INFO, WARN, ERROR + VERBOSE, DEBUG, INFO, WARN, ERROR } private static Level threshold = Level.INFO; @@ -36,6 +36,13 @@ public static boolean isEnabled(Level level) { return level.ordinal() >= threshold.ordinal(); } + public static void v(String message) { + if (isEnabled(Level.VERBOSE)) { + Log.v(TAG, message); + System.out.println(PREFIX + "VERBOSE: " + message); + } + } + public static void d(String message) { if (isEnabled(Level.DEBUG)) { Log.d(TAG, message); From 19ca02cd8f1a7554cd7c895482dca87134378baf Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Tue, 8 Jun 2021 19:14:20 +0300 Subject: [PATCH 5/9] Log control messages in verbose mode PR #2371 Signed-off-by: Romain Vimont --- app/src/control_msg.c | 130 ++++++++++++++++++++++++++++++++++++++++++ app/src/control_msg.h | 3 + app/src/controller.c | 1 + 3 files changed, 134 insertions(+) diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 8908c5462a..aba4bd1661 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -1,6 +1,7 @@ #include "control_msg.h" #include +#include #include #include @@ -8,6 +9,52 @@ #include "util/log.h" #include "util/str_util.h" +/** + * Map an enum value to a string based on an array, without crashing on an + * out-of-bounds index. + */ +#define ENUM_TO_LABEL(labels, value) \ + ((size_t) (value) < ARRAY_LEN(labels) ? labels[value] : "???") + +#define KEYEVENT_ACTION_LABEL(value) \ + ENUM_TO_LABEL(android_keyevent_action_labels, value) + +#define MOTIONEVENT_ACTION_LABEL(value) \ + ENUM_TO_LABEL(android_motionevent_action_labels, value) + +#define SCREEN_POWER_MODE_LABEL(value) \ + ENUM_TO_LABEL(screen_power_mode_labels, value) + +static const char *const android_keyevent_action_labels[] = { + "down", + "up", + "multi", +}; + +static const char *const android_motionevent_action_labels[] = { + "down", + "up", + "move", + "cancel", + "outside", + "ponter-down", + "pointer-up", + "hover-move", + "scroll", + "hover-enter" + "hover-exit", + "btn-press", + "btn-release", +}; + +static const char *const screen_power_mode_labels[] = { + "off", + "doze", + "normal", + "doze-suspend", + "suspend", +}; + static void write_position(uint8_t *buf, const struct position *position) { buffer_write32be(&buf[0], position->point.x); @@ -93,6 +140,89 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) { } } +void +control_msg_log(const struct control_msg *msg) { +#define LOG_CMSG(fmt, ...) LOGV("input: " fmt, ## __VA_ARGS__) + switch (msg->type) { + case CONTROL_MSG_TYPE_INJECT_KEYCODE: + LOG_CMSG("key %-4s code=%d repeat=%" PRIu32 " meta=%06lx", + KEYEVENT_ACTION_LABEL(msg->inject_keycode.action), + (int) msg->inject_keycode.keycode, + msg->inject_keycode.repeat, + (long) msg->inject_keycode.metastate); + break; + case CONTROL_MSG_TYPE_INJECT_TEXT: + LOG_CMSG("text \"%s\"", msg->inject_text.text); + break; + case CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT: { + int action = msg->inject_touch_event.action + & AMOTION_EVENT_ACTION_MASK; + uint64_t id = msg->inject_touch_event.pointer_id; + if (id == POINTER_ID_MOUSE || id == POINTER_ID_VIRTUAL_FINGER) { + // string pointer id + LOG_CMSG("touch [id=%s] %-4s position=%" PRIi32 ",%" PRIi32 + " pressure=%g buttons=%06lx", + id == POINTER_ID_MOUSE ? "mouse" : "vfinger", + MOTIONEVENT_ACTION_LABEL(action), + msg->inject_touch_event.position.point.x, + msg->inject_touch_event.position.point.y, + msg->inject_touch_event.pressure, + (long) msg->inject_touch_event.buttons); + } else { + // numeric pointer id + LOG_CMSG("touch [id=%" PRIu64 "] %-4s position=%" PRIi32 ",%" + PRIi32 " pressure=%g buttons=%06lx", + id, + MOTIONEVENT_ACTION_LABEL(action), + msg->inject_touch_event.position.point.x, + msg->inject_touch_event.position.point.y, + msg->inject_touch_event.pressure, + (long) msg->inject_touch_event.buttons); + } + break; + } + case CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT: + LOG_CMSG("scroll position=%" PRIi32 ",%" PRIi32 " hscroll=%" PRIi32 + " vscroll=%" PRIi32, + msg->inject_scroll_event.position.point.x, + msg->inject_scroll_event.position.point.y, + msg->inject_scroll_event.hscroll, + msg->inject_scroll_event.vscroll); + break; + case CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON: + LOG_CMSG("back-or-screen-on %s", + KEYEVENT_ACTION_LABEL(msg->inject_keycode.action)); + break; + case CONTROL_MSG_TYPE_SET_CLIPBOARD: + LOG_CMSG("clipboard %s \"%s\"", + msg->set_clipboard.paste ? "paste" : "copy", + msg->set_clipboard.text); + break; + case CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE: + LOG_CMSG("power mode %s", + SCREEN_POWER_MODE_LABEL(msg->set_screen_power_mode.mode)); + break; + case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL: + LOG_CMSG("expand notification panel"); + break; + case CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL: + LOG_CMSG("expand settings panel"); + break; + case CONTROL_MSG_TYPE_COLLAPSE_PANELS: + LOG_CMSG("collapse panels"); + break; + case CONTROL_MSG_TYPE_GET_CLIPBOARD: + LOG_CMSG("get clipboard"); + break; + case CONTROL_MSG_TYPE_ROTATE_DEVICE: + LOG_CMSG("rotate device"); + break; + default: + LOG_CMSG("unknown type: %u", (unsigned) msg->type); + break; + } +} + void control_msg_destroy(struct control_msg *msg) { switch (msg->type) { diff --git a/app/src/control_msg.h b/app/src/control_msg.h index a259d0db42..920a493ae3 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -84,6 +84,9 @@ struct control_msg { size_t control_msg_serialize(const struct control_msg *msg, unsigned char *buf); +void +control_msg_log(const struct control_msg *msg); + void control_msg_destroy(struct control_msg *msg); diff --git a/app/src/controller.c b/app/src/controller.c index 38b5e7027f..9284ae526d 100644 --- a/app/src/controller.c +++ b/app/src/controller.c @@ -48,6 +48,7 @@ controller_destroy(struct controller *controller) { bool controller_push_msg(struct controller *controller, const struct control_msg *msg) { + control_msg_log(msg); sc_mutex_lock(&controller->mutex); bool was_empty = cbuf_is_empty(&controller->queue); bool res = cbuf_push(&controller->queue, *msg); From 1039f9b531e57f710432073b2fd525d8ecb857c5 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Jun 2021 01:30:06 +0200 Subject: [PATCH 6/9] Workaround PRIu64 on Windows On Windows, PRIu64 is defined to "llu", which is not supported: error: unknown conversion type character 'l' in format --- app/src/control_msg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/control_msg.c b/app/src/control_msg.c index aba4bd1661..1257010ec7 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -170,7 +170,12 @@ control_msg_log(const struct control_msg *msg) { (long) msg->inject_touch_event.buttons); } else { // numeric pointer id - LOG_CMSG("touch [id=%" PRIu64 "] %-4s position=%" PRIi32 ",%" +#ifndef __WIN32 +# define PRIu64_ PRIu64 +#else +# define PRIu64_ "I64u" // Windows... +#endif + LOG_CMSG("touch [id=%" PRIu64_ "] %-4s position=%" PRIi32 ",%" PRIi32 " pressure=%g buttons=%06lx", id, MOTIONEVENT_ACTION_LABEL(action), From 5c95d18beb55e9dc24bf8b650042fcabeccce63f Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Jun 2021 12:46:41 +0200 Subject: [PATCH 7/9] Move log level conversion to log API --- app/meson.build | 1 + app/src/main.c | 23 +---------------------- app/src/util/log.c | 28 ++++++++++++++++++++++++++++ app/src/util/log.h | 11 +++++++++-- 4 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 app/src/util/log.c diff --git a/app/meson.build b/app/meson.build index 6b6991aade..0663c641db 100644 --- a/app/meson.build +++ b/app/meson.build @@ -20,6 +20,7 @@ src = [ 'src/stream.c', 'src/tiny_xpm.c', 'src/video_buffer.c', + 'src/util/log.c', 'src/util/net.c', 'src/util/process.c', 'src/util/str_util.c', diff --git a/app/src/main.c b/app/src/main.c index c3a7ad2eae..2afa3c4ea8 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -38,26 +38,6 @@ print_version(void) { #endif } -static SDL_LogPriority -convert_log_level_to_sdl(enum sc_log_level level) { - switch (level) { - case SC_LOG_LEVEL_VERBOSE: - return SDL_LOG_PRIORITY_VERBOSE; - case SC_LOG_LEVEL_DEBUG: - return SDL_LOG_PRIORITY_DEBUG; - case SC_LOG_LEVEL_INFO: - return SDL_LOG_PRIORITY_INFO; - case SC_LOG_LEVEL_WARN: - return SDL_LOG_PRIORITY_WARN; - case SC_LOG_LEVEL_ERROR: - return SDL_LOG_PRIORITY_ERROR; - default: - assert(!"unexpected log level"); - return SDL_LOG_PRIORITY_INFO; - } -} - - int main(int argc, char *argv[]) { #ifdef __WINDOWS__ @@ -81,8 +61,7 @@ main(int argc, char *argv[]) { return 1; } - SDL_LogPriority sdl_log = convert_log_level_to_sdl(args.opts.log_level); - SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, sdl_log); + sc_set_log_level(args.opts.log_level); if (args.help) { scrcpy_print_usage(argv[0]); diff --git a/app/src/util/log.c b/app/src/util/log.c new file mode 100644 index 0000000000..ac26de1cd8 --- /dev/null +++ b/app/src/util/log.c @@ -0,0 +1,28 @@ +#include "log.h" + +#include + +static SDL_LogPriority +log_level_sc_to_sdl(enum sc_log_level level) { + switch (level) { + case SC_LOG_LEVEL_VERBOSE: + return SDL_LOG_PRIORITY_VERBOSE; + case SC_LOG_LEVEL_DEBUG: + return SDL_LOG_PRIORITY_DEBUG; + case SC_LOG_LEVEL_INFO: + return SDL_LOG_PRIORITY_INFO; + case SC_LOG_LEVEL_WARN: + return SDL_LOG_PRIORITY_WARN; + case SC_LOG_LEVEL_ERROR: + return SDL_LOG_PRIORITY_ERROR; + default: + assert(!"unexpected log level"); + return SDL_LOG_PRIORITY_INFO; + } +} + +void +sc_set_log_level(enum sc_log_level level) { + SDL_LogPriority sdl_log = log_level_sc_to_sdl(level); + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, sdl_log); +} diff --git a/app/src/util/log.h b/app/src/util/log.h index 5955c7fb9e..8b6c175e28 100644 --- a/app/src/util/log.h +++ b/app/src/util/log.h @@ -1,8 +1,12 @@ -#ifndef LOG_H -#define LOG_H +#ifndef SC_LOG_H +#define SC_LOG_H + +#include "common.h" #include +#include "scrcpy.h" + #define LOGV(...) SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) #define LOGD(...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) #define LOGI(...) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) @@ -10,4 +14,7 @@ #define LOGE(...) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) #define LOGC(...) SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) +void +sc_set_log_level(enum sc_log_level level); + #endif From 488991116b9c56112a26daa1bb1069b57b9832ec Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Jun 2021 12:49:45 +0200 Subject: [PATCH 8/9] Expose function to get the current log level This will allow to avoid unnecessary processing for creating logs which will be discarded anyway. --- app/src/util/log.c | 25 +++++++++++++++++++++++++ app/src/util/log.h | 3 +++ 2 files changed, 28 insertions(+) diff --git a/app/src/util/log.c b/app/src/util/log.c index ac26de1cd8..a285fffba9 100644 --- a/app/src/util/log.c +++ b/app/src/util/log.c @@ -21,8 +21,33 @@ log_level_sc_to_sdl(enum sc_log_level level) { } } +static enum sc_log_level +log_level_sdl_to_sc(SDL_LogPriority priority) { + switch (priority) { + case SDL_LOG_PRIORITY_VERBOSE: + return SC_LOG_LEVEL_VERBOSE; + case SDL_LOG_PRIORITY_DEBUG: + return SC_LOG_LEVEL_DEBUG; + case SDL_LOG_PRIORITY_INFO: + return SC_LOG_LEVEL_INFO; + case SDL_LOG_PRIORITY_WARN: + return SC_LOG_LEVEL_WARN; + case SDL_LOG_PRIORITY_ERROR: + return SC_LOG_LEVEL_ERROR; + default: + assert(!"unexpected log level"); + return SC_LOG_LEVEL_INFO; + } +} + void sc_set_log_level(enum sc_log_level level) { SDL_LogPriority sdl_log = log_level_sc_to_sdl(level); SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, sdl_log); } + +enum sc_log_level +sc_get_log_level(void) { + SDL_LogPriority sdl_log = SDL_LogGetPriority(SDL_LOG_CATEGORY_APPLICATION); + return log_level_sdl_to_sc(sdl_log); +} diff --git a/app/src/util/log.h b/app/src/util/log.h index 8b6c175e28..30934b5c9f 100644 --- a/app/src/util/log.h +++ b/app/src/util/log.h @@ -17,4 +17,7 @@ void sc_set_log_level(enum sc_log_level level); +enum sc_log_level +sc_get_log_level(void); + #endif From 0de534d3bc30ff538801cc71324fd4139a31eafc Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 20 Jun 2021 12:54:09 +0200 Subject: [PATCH 9/9] Attempt to log message only in verbose mode If the log level is not verbose, there is no need to attept to log control messages at all. --- app/src/controller.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/controller.c b/app/src/controller.c index 9284ae526d..3a428aa865 100644 --- a/app/src/controller.c +++ b/app/src/controller.c @@ -48,7 +48,10 @@ controller_destroy(struct controller *controller) { bool controller_push_msg(struct controller *controller, const struct control_msg *msg) { - control_msg_log(msg); + if (sc_get_log_level() <= SC_LOG_LEVEL_VERBOSE) { + control_msg_log(msg); + } + sc_mutex_lock(&controller->mutex); bool was_empty = cbuf_is_empty(&controller->queue); bool res = cbuf_push(&controller->queue, *msg);