mirror of https://github.com/Genymobile/scrcpy
Introduce non-droppable control messages
Control messages are queued from the main thread and sent to the device from a separate thread. When the queue is full, messages are just dropped. This avoids to accumulate too much delay between the client and the device in case of network issue. However, some messages should not be dropped: for example, dropping a UHID_CREATE message would make all further UHID_INPUT messages invalid. Therefore, mark these messages as non-droppable. A non-droppable event is queued anyway (resizing the queue if necessary, unless the allocation fails). PR #5270 <https://github.com/Genymobile/scrcpy/pull/5270>
This commit is contained in:
parent
a84b0dfd0c
commit
49c8ca34fd
|
@ -278,6 +278,13 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
sc_control_msg_is_droppable(const struct sc_control_msg *msg) {
|
||||
// Cannot drop UHID_CREATE messages, because it would cause all further
|
||||
// UHID_INPUT messages for this device to be invalid
|
||||
return msg->type != SC_CONTROL_MSG_TYPE_UHID_CREATE;
|
||||
}
|
||||
|
||||
void
|
||||
sc_control_msg_destroy(struct sc_control_msg *msg) {
|
||||
switch (msg->type) {
|
||||
|
|
|
@ -116,6 +116,11 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf);
|
|||
void
|
||||
sc_control_msg_log(const struct sc_control_msg *msg);
|
||||
|
||||
// Even when the buffer is "full", some messages must absolutely not be dropped
|
||||
// to avoid inconsistencies.
|
||||
bool
|
||||
sc_control_msg_is_droppable(const struct sc_control_msg *msg);
|
||||
|
||||
void
|
||||
sc_control_msg_destroy(struct sc_control_msg *msg);
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
#include "util/log.h"
|
||||
|
||||
#define SC_CONTROL_MSG_QUEUE_MAX 64
|
||||
// Drop droppable events above this limit
|
||||
#define SC_CONTROL_MSG_QUEUE_LIMIT 60
|
||||
|
||||
static void
|
||||
sc_controller_receiver_on_ended(struct sc_receiver *receiver, bool error,
|
||||
|
@ -22,7 +23,9 @@ sc_controller_init(struct sc_controller *controller, sc_socket control_socket,
|
|||
void *cbs_userdata) {
|
||||
sc_vecdeque_init(&controller->queue);
|
||||
|
||||
bool ok = sc_vecdeque_reserve(&controller->queue, SC_CONTROL_MSG_QUEUE_MAX);
|
||||
// Add 4 to support 4 non-droppable events without re-allocation
|
||||
bool ok = sc_vecdeque_reserve(&controller->queue,
|
||||
SC_CONTROL_MSG_QUEUE_LIMIT + 4);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
@ -93,20 +96,31 @@ sc_controller_push_msg(struct sc_controller *controller,
|
|||
sc_control_msg_log(msg);
|
||||
}
|
||||
|
||||
bool pushed = false;
|
||||
|
||||
sc_mutex_lock(&controller->mutex);
|
||||
bool full = sc_vecdeque_is_full(&controller->queue);
|
||||
if (!full) {
|
||||
size_t size = sc_vecdeque_size(&controller->queue);
|
||||
if (size < SC_CONTROL_MSG_QUEUE_LIMIT) {
|
||||
bool was_empty = sc_vecdeque_is_empty(&controller->queue);
|
||||
sc_vecdeque_push_noresize(&controller->queue, *msg);
|
||||
pushed = true;
|
||||
if (was_empty) {
|
||||
sc_cond_signal(&controller->msg_cond);
|
||||
}
|
||||
} else if (!sc_control_msg_is_droppable(msg)) {
|
||||
bool ok = sc_vecdeque_push(&controller->queue, *msg);
|
||||
if (ok) {
|
||||
pushed = true;
|
||||
} else {
|
||||
// A non-droppable event must be dropped anyway
|
||||
LOG_OOM();
|
||||
}
|
||||
// Otherwise (if the queue is full), the msg is discarded
|
||||
}
|
||||
// Otherwise, the msg is discarded
|
||||
|
||||
sc_mutex_unlock(&controller->mutex);
|
||||
|
||||
return !full;
|
||||
return pushed;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
Loading…
Reference in New Issue