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

133 lines
7.7 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 <QList>
#include <QObject>
class AdbUtils final : public QObject {
Q_OBJECT
public:
explicit AdbUtils(QObject *parent = nullptr);
static QString adbPath();
static QList<QPair<QString, QString> > getListDevices();
static QString tryToGetRunningAppPid(const QString &deviceId, const QString &packageName);
static bool tryToStartApplication(const QString &deviceId, const QString &packageName);
static bool tryToKillApplication(const QString &deviceId, const QString &packageName);
static QString getScreenDumpAsXml(const QString &deviceId, int idx, bool screenshot = false);
// Сырой дамп без фильтра "useful UI" — для ручного превью оператора:
// отдаёт что есть на экране, даже если это PIN-пад / сплэш / WebView-shell.
static QString getRawScreenDumpAsXml(const QString &deviceId);
static bool takeScreenshot(const QString &deviceId, const QString &name);
// IP телефона в Wi-Fi (кэш по serial с TTL). Для IP:port-серийника берётся из
// серийника, иначе `adb shell ip route get 1.1.1.1` → src. Пусто, если не в Wi-Fi.
// Используется и для http-скриншота, и для сохранения IP в БД (wifi_connections).
static QString resolvePhoneIp(const QString &deviceId);
// Текущий режим скриншотов устройства: "http" | "exec-out (fallback)" | "" (ещё не
// определялся). Для индикации в UI. Ключ — adb-серийник.
static QString screenshotMode(const QString &deviceId);
// Захватывает скриншот напрямую в память (PNG-байты), без временного файла.
// Выбирает стратегию по config.ini [screenshot] transport: http (через APK
// arc-shot, мимо adb) с fallback на exec-out, либо сразу exec-out.
static QByteArray captureScreenshotBytes(const QString &deviceId);
// Скриншот через APK arc-shot: adb screencap в файл на /sdcard (дёшево, без
// передачи байтов через adb) + HTTP-GET файла напрямую с телефона по его
// Wi-Fi IP. Разгружает adb. Пусто при недоступности (нет APK/сети) — вызывающий
// откатывается на exec-out. Возвращает PNG-байты.
static QByteArray captureScreenshotHttp(const QString &deviceId);
static bool takeXmlDump(const QString &deviceId, const QString &name);
static bool makeTap(const QString &deviceId, int x, int y);
static bool enableAdbIMEKeyboard(const QString &deviceId);
static bool inputAdbIMEText(const QString &deviceId, const QString &text);
static bool disableAdbIMEKeyboard(const QString &deviceId);
static bool makeSwipe(const QString &deviceId, int x1, int y1, int x2, int y2);
static bool makeSwipe(const QString &deviceId, int x1, int y1, int x2, int y2, int durationMs);
static bool inputText(const QString &deviceId, const QString &text);
static bool hideKeyboard(const QString &deviceId);
static bool goBack(const QString &deviceId);
static void unlockScreen(const QString &deviceId, int screenWidth, int screenHeight);
static QSet<QString> getListApps(const QString &deviceId);
// Возвращает таймзону устройства (напр. "Asia/Bangkok"), либо пустую строку при ошибке
static QString getDeviceTimezone(const QString &deviceId);
// Возвращает versionName установленного пакета (напр. "19.17.0"), либо пустую строку при ошибке/отсутствии
static QString getAppVersion(const QString &deviceId, const QString &packageName);
// Возвращает пакет приложения на переднем плане (foreground), либо пустую строку при ошибке
static QString getForegroundPackage(const QString &deviceId);
// Проверяет реальную ориентацию экрана (dumpsys input → SurfaceOrientation).
// Если экран в горизонтальной ориентации (landscape, 90°/270°), принудительно
// ставит вертикальную: выключает автоповорот и выставляет user_rotation=0.
// Best-effort: при ошибке adb просто ничего не делает. Возвращает true, если
// экран в портрете (изначально или после форсирования).
static bool ensurePortraitOrientation(const QString &deviceId);
// --- ADB через Wi-Fi (TCP/IP) ---
// Эвристика: serial выглядит как сетевой endpoint "ip:port" (Wi-Fi-подключение),
// а не USB-серийник (hex) или emulator-XXXX.
static bool isWirelessSerial(const QString &serial);
// Возвращает IPv4-адрес устройства в сети Wi-Fi (интерфейс wlan0), либо пустую
// строку, если устройство не в Wi-Fi / адрес не прочитался.
static QString getDeviceWifiIp(const QString &serial);
// Возвращает MAC-адрес интерфейса wlan0 в нормализованном виде (lower-case,
// разделитель ':'), либо пустую строку. Нужен, чтобы находить устройство в сети
// после смены IP по DHCP (поиск по ARP-таблице).
static QString getDeviceMac(const QString &serial);
// Переводит adbd устройства в TCP-режим на указанном порту (adb -s <serial> tcpip <port>).
// Вызывается на устройстве, подключённом по USB. ВНИМАНИЕ: перезапускает adbd и
// кратковременно рвёт текущее соединение — запускать только на простаивающем устройстве.
static bool enableTcpip(const QString &serial, int port);
// adb connect <endpoint> (endpoint вида "192.168.1.50:5555").
// Возвращает true при "connected"/"already connected". Exit-code adb недостаточен —
// adb connect возвращает 0 даже при "failed to connect", поэтому разбираем stdout.
static bool connectWireless(const QString &endpoint);
// adb disconnect <endpoint>.
static bool disconnectWireless(const QString &endpoint);
private:
static QString adbDir();
static bool startProcess(const QString &program, const QStringList &args,
QString *stdOut = nullptr, QString *stdErr = nullptr);
// Старый способ: exec-out screencap -p (стримит PNG через adb). Fallback для http.
static QByteArray captureScreenshotExecOut(const QString &deviceId);
// Синхронный HTTP/1.0 GET по QTcpSocket (без event-loop, безопасно из worker-потоков).
// Возвращает тело ответа при 200, иначе пусто.
static QByteArray httpGet(const QString &ip, int port, const QString &path, int timeoutMs);
// Поднимает foreground-сервис arc-shot (ставит APK, если удалён). Дёргается из
// http-fail ветки, т.е. не чаще раза в бэкофф-окно.
static void kickArcShot(const QString &deviceId);
};