mirror of https://github.com/Genymobile/scrcpy
Unregister all AOA devices automatically on exit
Pushing a close event from the keyboard_aoa or mouse_aoa implementation was racy, because the AOA thread might be stopped before these events were processed. Instead, keep the list of open AOA devices to close them automatically from the AOA thread before exiting. PR #5270 <https://github.com/Genymobile/scrcpy/pull/5270>
This commit is contained in:
parent
6c707ad8a3
commit
222916eebe
|
@ -7,6 +7,7 @@
|
|||
#include "aoa_hid.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
// See <https://source.android.com/devices/accessories/aoa2#hid-support>.
|
||||
#define ACCESSORY_REGISTER_HID 54
|
||||
|
@ -19,6 +20,8 @@
|
|||
// Drop droppable events above this limit
|
||||
#define SC_AOA_EVENT_QUEUE_LIMIT 60
|
||||
|
||||
struct sc_vec_hid_ids SC_VECTOR(uint16_t);
|
||||
|
||||
static void
|
||||
sc_hid_input_log(const struct sc_hid_input *hid_input) {
|
||||
// HID input: [00] FF FF FF FF...
|
||||
|
@ -309,7 +312,8 @@ sc_aoa_push_close(struct sc_aoa *aoa, const struct sc_hid_close *hid_close) {
|
|||
}
|
||||
|
||||
static bool
|
||||
sc_aoa_process_event(struct sc_aoa *aoa, struct sc_aoa_event *event) {
|
||||
sc_aoa_process_event(struct sc_aoa *aoa, struct sc_aoa_event *event,
|
||||
struct sc_vec_hid_ids *vec_open) {
|
||||
switch (event->type) {
|
||||
case SC_AOA_EVENT_TYPE_INPUT: {
|
||||
uint64_t ack_to_wait = event->input.ack_to_wait;
|
||||
|
@ -350,7 +354,16 @@ sc_aoa_process_event(struct sc_aoa *aoa, struct sc_aoa_event *event) {
|
|||
bool ok = sc_aoa_setup_hid(aoa, hid_open->hid_id,
|
||||
hid_open->report_desc,
|
||||
hid_open->report_desc_size);
|
||||
if (!ok) {
|
||||
if (ok) {
|
||||
// The device is now open, add it to the list of devices to
|
||||
// close automatically on exit
|
||||
bool pushed = sc_vector_push(vec_open, hid_open->hid_id);
|
||||
if (!pushed) {
|
||||
LOG_OOM();
|
||||
// this is not fatal, the HID device will just not be
|
||||
// explicitly unregistered
|
||||
}
|
||||
} else {
|
||||
LOGW("Could not open AOA device: %" PRIu16, hid_open->hid_id);
|
||||
}
|
||||
|
||||
|
@ -359,7 +372,14 @@ sc_aoa_process_event(struct sc_aoa *aoa, struct sc_aoa_event *event) {
|
|||
case SC_AOA_EVENT_TYPE_CLOSE: {
|
||||
struct sc_hid_close *hid_close = &event->close.hid;
|
||||
bool ok = sc_aoa_unregister_hid(aoa, hid_close->hid_id);
|
||||
if (!ok) {
|
||||
if (ok) {
|
||||
// The device is not open anymore, remove it from the list of
|
||||
// devices to close automatically on exit
|
||||
ssize_t idx = sc_vector_index_of(vec_open, hid_close->hid_id);
|
||||
if (idx >= 0) {
|
||||
sc_vector_remove(vec_open, idx);
|
||||
}
|
||||
} else {
|
||||
LOGW("Could not close AOA device: %" PRIu16, hid_close->hid_id);
|
||||
}
|
||||
|
||||
|
@ -375,6 +395,9 @@ static int
|
|||
run_aoa_thread(void *data) {
|
||||
struct sc_aoa *aoa = data;
|
||||
|
||||
// Store the HID ids of opened devices to unregister them all before exiting
|
||||
struct sc_vec_hid_ids vec_open = SC_VECTOR_INITIALIZER;
|
||||
|
||||
for (;;) {
|
||||
sc_mutex_lock(&aoa->mutex);
|
||||
while (!aoa->stopped && sc_vecdeque_is_empty(&aoa->queue)) {
|
||||
|
@ -390,12 +413,24 @@ run_aoa_thread(void *data) {
|
|||
struct sc_aoa_event event = sc_vecdeque_pop(&aoa->queue);
|
||||
sc_mutex_unlock(&aoa->mutex);
|
||||
|
||||
bool cont = sc_aoa_process_event(aoa, &event);
|
||||
bool cont = sc_aoa_process_event(aoa, &event, &vec_open);
|
||||
if (!cont) {
|
||||
// stopped
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly unregister all registered HID ids before exiting
|
||||
for (size_t i = 0; i < vec_open.size; ++i) {
|
||||
uint16_t hid_id = vec_open.data[i];
|
||||
LOGD("Unregistering AOA device %" PRIu16 "...", hid_id);
|
||||
bool ok = sc_aoa_unregister_hid(aoa, hid_id);
|
||||
if (!ok) {
|
||||
LOGW("Could not close AOA device: %" PRIu16, hid_id);
|
||||
}
|
||||
}
|
||||
sc_vector_destroy(&vec_open);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,11 +98,6 @@ sc_keyboard_aoa_init(struct sc_keyboard_aoa *kb, struct sc_aoa *aoa) {
|
|||
|
||||
void
|
||||
sc_keyboard_aoa_destroy(struct sc_keyboard_aoa *kb) {
|
||||
struct sc_hid_close hid_close;
|
||||
sc_hid_keyboard_generate_close(&hid_close);
|
||||
|
||||
bool ok = sc_aoa_push_close(kb->aoa, &hid_close);
|
||||
if (!ok) {
|
||||
LOGW("Could not push AOA HID close (keyboard)");
|
||||
}
|
||||
(void) kb;
|
||||
// Do nothing, kb->aoa will automatically unregister all devices
|
||||
}
|
||||
|
|
|
@ -78,11 +78,6 @@ sc_mouse_aoa_init(struct sc_mouse_aoa *mouse, struct sc_aoa *aoa) {
|
|||
|
||||
void
|
||||
sc_mouse_aoa_destroy(struct sc_mouse_aoa *mouse) {
|
||||
struct sc_hid_close hid_close;
|
||||
sc_hid_mouse_generate_close(&hid_close);
|
||||
|
||||
bool ok = sc_aoa_push_close(mouse->aoa, &hid_close);
|
||||
if (!ok) {
|
||||
LOGW("Could not push AOA HID close (mouse)");
|
||||
}
|
||||
(void) mouse;
|
||||
// Do nothing, mouse->aoa will automatically unregister all devices
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue