1
0
forked from BRT/arc
arc/android/adb/WifiAdbManager.h

73 lines
4.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <QMap>
#include <QSet>
#include <QString>
// Автоматическое поднятие/восстановление беспроводного (Wi-Fi, ADB over TCP/IP)
// подключения к Android-устройствам. Без участия оператора: USB остаётся основным
// транспортом, Wi-Fi — горячий резерв, который подхватывается при отключении кабеля.
//
// Сохранённые эндпоинты хранятся в реляционной таблице wifi_connections
// (WifiConnectionDAO), по строке на android_id: ip/port (= endpoint "ip:port") + mac.
// MAC нужен, чтобы найти устройство после смены IP по DHCP (поиск в ARP-таблице).
// WifiAdbManager — единственный владелец записи в этой таблице.
//
// Все методы статические и блокирующие (дёргают adb/arp/ping через QProcess) —
// вызывать из фонового потока (DeviceScreener), не из GUI-потока.
// Сохранённый беспроводной эндпоинт устройства.
struct WifiEndpoint {
QString endpoint; // "ip:port"
QString mac; // нормализованный MAC (lower-case, разделитель ':'); может быть пустым
};
class WifiAdbManager {
public:
// Параметры одного прохода переподключения сохранённых эндпоинтов.
struct ReconnectOptions {
QSet<QString> alreadyOnline; // android_id, уже видимые онлайн — пропускаем
QSet<QString> staleEndpoints; // "ip:port" в статусе offline — disconnect перед connect
bool macRediscover = false; // при неудаче искать новый IP устройства по MAC
bool subnetSweep = false; // разрешить ping-скан подсети для прогрева ARP (медленно/шумно)
};
// Сохранённые эндпоинты: android_id → WifiEndpoint.
static QMap<QString, WifiEndpoint> loadEndpoints();
// Пытается `adb connect` по всем сохранённым эндпоинтам (для устройств, которых
// ещё нет онлайн). Возвращает число успешно подключённых.
static int reconnectKnown(const ReconnectOptions &opts);
// Принудительно пересоздаёт TCP-соединение Wi-Fi-эндпоинта устройства
// (disconnect → connect). Нужен, когда соединение «залипло» в полумёртвом
// состоянии: adb держит эндпоинт как "device", но команды к нему виснут (устройство
// уходит в debounced-offline, при этом в `adb devices` НЕ появляется статус
// "offline"). Голый connect в этом случае вернул бы "already connected" и не помог.
// No-op, если у устройства нет сохранённого Wi-Fi-эндпоинта (например, офлайн по USB).
// Возвращает true, если после переподключения соединение поднялось.
static bool kickEndpoint(const QString &androidId);
// Bootstrap беспроводного эндпоинта для устройства, подключённого по USB:
// снять MAC → tcpip <port> → определить wlan0 IP → adb connect → сохранить эндпоинт.
// ВНИМАНИЕ: tcpip рвёт adbd — вызывать только для простаивающего устройства.
// Возвращает "ip:port" при успехе, пустую строку при неудаче.
static QString tryBootstrap(const QString &usbSerial, const QString &androidId, int port);
// Удаляет сохранённый эндпоинт и делает adb disconnect (best-effort).
static void forget(const QString &androidId);
private:
static void saveEndpoint(const QString &androidId, const QString &endpoint, const QString &mac);
// Поиск текущего IP устройства по известному MAC (после смены IP по DHCP).
// subnetHintIp — последний известный IP (для определения /24 при ping-скане).
static QString findIpByMac(const QString &mac, const QString &subnetHintIp, bool allowSweep);
static QString arpLookupIp(const QString &normalizedMac);
static void pingSweepSubnet(const QString &subnetHintIp);
static QString normalizeMac(const QString &mac);
static QString ipOf(const QString &endpoint);
static QString portOf(const QString &endpoint);
};