Use vector for listing ADB devices

This avoids the hardcoded maximum number of ADB devices detected (16).

Refs #3029 <https://github.com/Genymobile/scrcpy/pull/3029>
PR #3035 <https://github.com/Genymobile/scrcpy/pull/3035>

Co-authored-by: Daniel Ansorregui <d.ansorregui@samsung.com>
This commit is contained in:
Romain Vimont 2022-02-18 21:16:53 +01:00
parent 1790e88278
commit 4b8cb042c4
6 changed files with 95 additions and 85 deletions

View file

@ -5,6 +5,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "adb_device.h"
#include "adb_parser.h" #include "adb_parser.h"
#include "util/file.h" #include "util/file.h"
#include "util/log.h" #include "util/log.h"
@ -392,16 +393,16 @@ sc_adb_disconnect(struct sc_intr *intr, const char *ip_port, unsigned flags) {
return process_check_success_intr(intr, pid, "adb disconnect", flags); return process_check_success_intr(intr, pid, "adb disconnect", flags);
} }
static ssize_t static bool
sc_adb_list_devices(struct sc_intr *intr, unsigned flags, sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
struct sc_adb_device *devices, size_t len) { struct sc_vec_adb_devices *out_vec) {
const char *const argv[] = SC_ADB_COMMAND("devices", "-l"); const char *const argv[] = SC_ADB_COMMAND("devices", "-l");
sc_pipe pout; sc_pipe pout;
sc_pid pid = sc_adb_execute_p(argv, flags, &pout); sc_pid pid = sc_adb_execute_p(argv, flags, &pout);
if (pid == SC_PROCESS_NONE) { if (pid == SC_PROCESS_NONE) {
LOGE("Could not execute \"adb devices -l\""); LOGE("Could not execute \"adb devices -l\"");
return -1; return false;
} }
char buf[4096]; char buf[4096];
@ -410,11 +411,11 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
bool ok = process_check_success_intr(intr, pid, "adb devices -l", flags); bool ok = process_check_success_intr(intr, pid, "adb devices -l", flags);
if (!ok) { if (!ok) {
return -1; return false;
} }
if (r == -1) { if (r == -1) {
return -1; return false;
} }
assert((size_t) r < sizeof(buf)); assert((size_t) r < sizeof(buf));
@ -423,14 +424,14 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
// in the buffer in a single pass // in the buffer in a single pass
LOGW("Result of \"adb devices -l\" does not fit in 4Kb. " LOGW("Result of \"adb devices -l\" does not fit in 4Kb. "
"Please report an issue."); "Please report an issue.");
return -1; return false;
} }
// It is parsed as a NUL-terminated string // It is parsed as a NUL-terminated string
buf[r] = '\0'; buf[r] = '\0';
// List all devices to the output list directly // List all devices to the output list directly
return sc_adb_parse_devices(buf, devices, len); return sc_adb_parse_devices(buf, out_vec);
} }
static bool static bool
@ -529,22 +530,21 @@ bool
sc_adb_select_device(struct sc_intr *intr, sc_adb_select_device(struct sc_intr *intr,
const struct sc_adb_device_selector *selector, const struct sc_adb_device_selector *selector,
unsigned flags, struct sc_adb_device *out_device) { unsigned flags, struct sc_adb_device *out_device) {
struct sc_adb_device devices[16]; struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
ssize_t count = bool ok = sc_adb_list_devices(intr, flags, &vec);
sc_adb_list_devices(intr, flags, devices, ARRAY_LEN(devices)); if (!ok) {
if (count == -1) {
LOGE("Could not list ADB devices"); LOGE("Could not list ADB devices");
return false; return false;
} }
if (count == 0) { if (vec.size == 0) {
LOGE("Could not find any ADB device"); LOGE("Could not find any ADB device");
return false; return false;
} }
size_t sel_idx; // index of the single matching device if sel_count == 1 size_t sel_idx; // index of the single matching device if sel_count == 1
size_t sel_count = size_t sel_count =
sc_adb_devices_select(devices, count, selector, &sel_idx); sc_adb_devices_select(vec.data, vec.size, selector, &sel_idx);
if (sel_count == 0) { if (sel_count == 0) {
// if count > 0 && sel_count == 0, then necessarily a selection is // if count > 0 && sel_count == 0, then necessarily a selection is
@ -567,8 +567,8 @@ sc_adb_select_device(struct sc_intr *intr,
break; break;
} }
sc_adb_devices_log(SC_LOG_LEVEL_ERROR, devices, count); sc_adb_devices_log(SC_LOG_LEVEL_ERROR, vec.data, vec.size);
sc_adb_devices_destroy_all(devices, count); sc_adb_devices_destroy(&vec);
return false; return false;
} }
@ -594,28 +594,28 @@ sc_adb_select_device(struct sc_intr *intr,
assert(!"Unexpected selector type"); assert(!"Unexpected selector type");
break; break;
} }
sc_adb_devices_log(SC_LOG_LEVEL_ERROR, devices, count); sc_adb_devices_log(SC_LOG_LEVEL_ERROR, vec.data, vec.size);
LOGE("Select a device via -s (--serial), -d (--select-usb) or -e " LOGE("Select a device via -s (--serial), -d (--select-usb) or -e "
"(--select-tcpip)"); "(--select-tcpip)");
sc_adb_devices_destroy_all(devices, count); sc_adb_devices_destroy(&vec);
return false; return false;
} }
assert(sel_count == 1); // sel_idx is valid only if sel_count == 1 assert(sel_count == 1); // sel_idx is valid only if sel_count == 1
struct sc_adb_device *device = &devices[sel_idx]; struct sc_adb_device *device = &vec.data[sel_idx];
bool ok = sc_adb_device_check_state(device, devices, count); ok = sc_adb_device_check_state(device, vec.data, vec.size);
if (!ok) { if (!ok) {
sc_adb_devices_destroy_all(devices, count); sc_adb_devices_destroy(&vec);
return false; return false;
} }
LOGD("ADB device found:"); LOGD("ADB device found:");
sc_adb_devices_log(SC_LOG_LEVEL_DEBUG, devices, count); sc_adb_devices_log(SC_LOG_LEVEL_DEBUG, vec.data, vec.size);
// Move devics into out_device (do not destroy device) // Move devics into out_device (do not destroy device)
sc_adb_device_move(out_device, device); sc_adb_device_move(out_device, device);
sc_adb_devices_destroy_all(devices, count); sc_adb_devices_destroy(&vec);
return true; return true;
} }

View file

@ -18,9 +18,10 @@ sc_adb_device_move(struct sc_adb_device *dst, struct sc_adb_device *src) {
} }
void void
sc_adb_devices_destroy_all(struct sc_adb_device *devices, size_t count) { sc_adb_devices_destroy(struct sc_vec_adb_devices *devices) {
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < devices->size; ++i) {
sc_adb_device_destroy(&devices[i]); sc_adb_device_destroy(&devices->data[i]);
} }
sc_vector_destroy(devices);
} }

View file

@ -6,6 +6,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include "util/vector.h"
struct sc_adb_device { struct sc_adb_device {
char *serial; char *serial;
char *state; char *state;
@ -13,6 +15,8 @@ struct sc_adb_device {
bool selected; bool selected;
}; };
struct sc_vec_adb_devices SC_VECTOR(struct sc_adb_device);
void void
sc_adb_device_destroy(struct sc_adb_device *device); sc_adb_device_destroy(struct sc_adb_device *device);
@ -29,6 +33,6 @@ void
sc_adb_device_move(struct sc_adb_device *dst, struct sc_adb_device *src); sc_adb_device_move(struct sc_adb_device *dst, struct sc_adb_device *src);
void void
sc_adb_devices_destroy_all(struct sc_adb_device *devices, size_t count); sc_adb_devices_destroy(struct sc_vec_adb_devices *devices);
#endif #endif

View file

@ -109,11 +109,8 @@ sc_adb_parse_device(char *line, struct sc_adb_device *device) {
return true; return true;
} }
ssize_t bool
sc_adb_parse_devices(char *str, struct sc_adb_device *devices, sc_adb_parse_devices(char *str, struct sc_vec_adb_devices *out_vec) {
size_t devices_len) {
size_t dev_count = 0;
#define HEADER "List of devices attached" #define HEADER "List of devices attached"
#define HEADER_LEN (sizeof(HEADER) - 1) #define HEADER_LEN (sizeof(HEADER) - 1)
bool header_found = false; bool header_found = false;
@ -144,25 +141,24 @@ sc_adb_parse_devices(char *str, struct sc_adb_device *devices,
size_t line_len = sc_str_remove_trailing_cr(line, len); size_t line_len = sc_str_remove_trailing_cr(line, len);
line[line_len] = '\0'; line[line_len] = '\0';
bool ok = sc_adb_parse_device(line, &devices[dev_count]); struct sc_adb_device device;
bool ok = sc_adb_parse_device(line, &device);
if (!ok) { if (!ok) {
continue; continue;
} }
++dev_count; ok = sc_vector_push(out_vec, device);
if (!ok) {
assert(dev_count <= devices_len); LOG_OOM();
if (dev_count == devices_len) { LOGE("Could not push adb_device to vector");
// Max number of devices reached sc_adb_device_destroy(&device);
break; // continue anyway
continue;
} }
} }
if (!header_found) { assert(header_found || out_vec->size == 0);
return -1; return header_found;
}
return dev_count;
} }
static char * static char *

View file

@ -14,9 +14,8 @@
* *
* Warning: this function modifies the buffer for optimization purposes. * Warning: this function modifies the buffer for optimization purposes.
*/ */
ssize_t bool
sc_adb_parse_devices(char *str, struct sc_adb_device *devices, sc_adb_parse_devices(char *str, struct sc_vec_adb_devices *out_vec);
size_t devices_len);
/** /**
* Parse the ip from the output of `adb shell ip route` * Parse the ip from the output of `adb shell ip route`

View file

@ -13,21 +13,22 @@ static void test_adb_devices() {
"192.168.1.1:5555 device product:MyWifiProduct model:MyWifiModel " "192.168.1.1:5555 device product:MyWifiProduct model:MyWifiModel "
"device:MyWifiDevice trandport_id:2\n"; "device:MyWifiDevice trandport_id:2\n";
struct sc_adb_device devices[16]; struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices)); bool ok = sc_adb_parse_devices(output, &vec);
assert(count == 2); assert(ok);
assert(vec.size == 2);
struct sc_adb_device *device = &devices[0]; struct sc_adb_device *device = &vec.data[0];
assert(!strcmp("0123456789abcdef", device->serial)); assert(!strcmp("0123456789abcdef", device->serial));
assert(!strcmp("device", device->state)); assert(!strcmp("device", device->state));
assert(!strcmp("MyModel", device->model)); assert(!strcmp("MyModel", device->model));
device = &devices[1]; device = &vec.data[1];
assert(!strcmp("192.168.1.1:5555", device->serial)); assert(!strcmp("192.168.1.1:5555", device->serial));
assert(!strcmp("device", device->state)); assert(!strcmp("device", device->state));
assert(!strcmp("MyWifiModel", device->model)); assert(!strcmp("MyWifiModel", device->model));
sc_adb_devices_destroy_all(devices, count); sc_adb_devices_destroy(&vec);
} }
static void test_adb_devices_cr() { static void test_adb_devices_cr() {
@ -38,21 +39,22 @@ static void test_adb_devices_cr() {
"192.168.1.1:5555 device product:MyWifiProduct model:MyWifiModel " "192.168.1.1:5555 device product:MyWifiProduct model:MyWifiModel "
"device:MyWifiDevice trandport_id:2\r\n"; "device:MyWifiDevice trandport_id:2\r\n";
struct sc_adb_device devices[16]; struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices)); bool ok = sc_adb_parse_devices(output, &vec);
assert(count == 2); assert(ok);
assert(vec.size == 2);
struct sc_adb_device *device = &devices[0]; struct sc_adb_device *device = &vec.data[0];
assert(!strcmp("0123456789abcdef", device->serial)); assert(!strcmp("0123456789abcdef", device->serial));
assert(!strcmp("device", device->state)); assert(!strcmp("device", device->state));
assert(!strcmp("MyModel", device->model)); assert(!strcmp("MyModel", device->model));
device = &devices[1]; device = &vec.data[1];
assert(!strcmp("192.168.1.1:5555", device->serial)); assert(!strcmp("192.168.1.1:5555", device->serial));
assert(!strcmp("device", device->state)); assert(!strcmp("device", device->state));
assert(!strcmp("MyWifiModel", device->model)); assert(!strcmp("MyWifiModel", device->model));
sc_adb_devices_destroy_all(devices, count); sc_adb_devices_destroy(&vec);
} }
static void test_adb_devices_daemon_start() { static void test_adb_devices_daemon_start() {
@ -63,16 +65,17 @@ static void test_adb_devices_daemon_start() {
"0123456789abcdef device usb:2-1 product:MyProduct model:MyModel " "0123456789abcdef device usb:2-1 product:MyProduct model:MyModel "
"device:MyDevice transport_id:1\n"; "device:MyDevice transport_id:1\n";
struct sc_adb_device devices[16]; struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices)); bool ok = sc_adb_parse_devices(output, &vec);
assert(count == 1); assert(ok);
assert(vec.size == 1);
struct sc_adb_device *device = &devices[0]; struct sc_adb_device *device = &vec.data[0];
assert(!strcmp("0123456789abcdef", device->serial)); assert(!strcmp("0123456789abcdef", device->serial));
assert(!strcmp("device", device->state)); assert(!strcmp("device", device->state));
assert(!strcmp("MyModel", device->model)); assert(!strcmp("MyModel", device->model));
sc_adb_device_destroy(device); sc_adb_devices_destroy(&vec);
} }
static void test_adb_devices_daemon_start_mixed() { static void test_adb_devices_daemon_start_mixed() {
@ -84,21 +87,22 @@ static void test_adb_devices_daemon_start_mixed() {
"87654321 device usb:2-1 product:MyProduct model:MyModel " "87654321 device usb:2-1 product:MyProduct model:MyModel "
"device:MyDevice\n"; "device:MyDevice\n";
struct sc_adb_device devices[16]; struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices)); bool ok = sc_adb_parse_devices(output, &vec);
assert(count == 2); assert(ok);
assert(vec.size == 2);
struct sc_adb_device *device = &devices[0]; struct sc_adb_device *device = &vec.data[0];
assert(!strcmp("0123456789abcdef", device->serial)); assert(!strcmp("0123456789abcdef", device->serial));
assert(!strcmp("unauthorized", device->state)); assert(!strcmp("unauthorized", device->state));
assert(!device->model); assert(!device->model);
device = &devices[1]; device = &vec.data[1];
assert(!strcmp("87654321", device->serial)); assert(!strcmp("87654321", device->serial));
assert(!strcmp("device", device->state)); assert(!strcmp("device", device->state));
assert(!strcmp("MyModel", device->model)); assert(!strcmp("MyModel", device->model));
sc_adb_devices_destroy_all(devices, count); sc_adb_devices_destroy(&vec);
} }
static void test_adb_devices_without_eol() { static void test_adb_devices_without_eol() {
@ -106,34 +110,39 @@ static void test_adb_devices_without_eol() {
"List of devices attached\n" "List of devices attached\n"
"0123456789abcdef device usb:2-1 product:MyProduct model:MyModel " "0123456789abcdef device usb:2-1 product:MyProduct model:MyModel "
"device:MyDevice transport_id:1"; "device:MyDevice transport_id:1";
struct sc_adb_device devices[16];
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices));
assert(count == 1);
struct sc_adb_device *device = &devices[0]; struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
bool ok = sc_adb_parse_devices(output, &vec);
assert(ok);
assert(vec.size == 1);
struct sc_adb_device *device = &vec.data[0];
assert(!strcmp("0123456789abcdef", device->serial)); assert(!strcmp("0123456789abcdef", device->serial));
assert(!strcmp("device", device->state)); assert(!strcmp("device", device->state));
assert(!strcmp("MyModel", device->model)); assert(!strcmp("MyModel", device->model));
sc_adb_device_destroy(device); sc_adb_devices_destroy(&vec);
} }
static void test_adb_devices_without_header() { static void test_adb_devices_without_header() {
char output[] = char output[] =
"0123456789abcdef device usb:2-1 product:MyProduct model:MyModel " "0123456789abcdef device usb:2-1 product:MyProduct model:MyModel "
"device:MyDevice transport_id:1\n"; "device:MyDevice transport_id:1\n";
struct sc_adb_device devices[16];
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices)); struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
assert(count == -1); bool ok = sc_adb_parse_devices(output, &vec);
assert(!ok);
} }
static void test_adb_devices_corrupted() { static void test_adb_devices_corrupted() {
char output[] = char output[] =
"List of devices attached\n" "List of devices attached\n"
"corrupted_garbage\n"; "corrupted_garbage\n";
struct sc_adb_device devices[16];
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices)); struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
assert(count == 0); bool ok = sc_adb_parse_devices(output, &vec);
assert(ok);
assert(vec.size == 0);
} }
static void test_adb_devices_spaces() { static void test_adb_devices_spaces() {
@ -141,16 +150,17 @@ static void test_adb_devices_spaces() {
"List of devices attached\n" "List of devices attached\n"
"0123456789abcdef unauthorized usb:1-4 transport_id:3\n"; "0123456789abcdef unauthorized usb:1-4 transport_id:3\n";
struct sc_adb_device devices[16]; struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
ssize_t count = sc_adb_parse_devices(output, devices, ARRAY_LEN(devices)); bool ok = sc_adb_parse_devices(output, &vec);
assert(count == 1); assert(ok);
assert(vec.size == 1);
struct sc_adb_device *device = &devices[0]; struct sc_adb_device *device = &vec.data[0];
assert(!strcmp("0123456789abcdef", device->serial)); assert(!strcmp("0123456789abcdef", device->serial));
assert(!strcmp("unauthorized", device->state)); assert(!strcmp("unauthorized", device->state));
assert(!device->model); assert(!device->model);
sc_adb_device_destroy(device); sc_adb_devices_destroy(&vec);
} }
static void test_get_ip_single_line() { static void test_get_ip_single_line() {