adb异常处理优化

This commit is contained in:
Elaina 2024-12-02 23:09:44 +08:00
parent b8b6285ff1
commit db94be4e4c
3 changed files with 53 additions and 60 deletions

View file

@ -4,7 +4,3 @@ class SimulatorError(Exception):
class GameError(Exception):
pass
class ADBError(Exception):
pass

View file

@ -10,12 +10,18 @@ from adbutils import AdbClient, AdbDevice
from mower import __system__
from mower.utils import config
from mower.utils.csleep import MowerExit, csleep
from mower.utils.device.exception import SimulatorError
from mower.utils.device.simulator import restart_simulator
from mower.utils.image import bytes2img
from mower.utils.log import logger
from .utils import subprocess_run
class ADBServerError(Exception):
pass
def retry_adb(func):
@wraps(func)
def retry_wrapper(self, *args, **kwargs):
@ -24,9 +30,15 @@ def retry_adb(func):
return func(self, *args, **kwargs)
except MowerExit:
raise
except ADBServerError as e:
logger.exception(e)
self.restart_server()
except SimulatorError as e:
logger.exception(e)
restart_simulator()
self._adb_device = None
except Exception as e:
logger.exception(e)
self.adb_reconnect()
return retry_wrapper
@ -38,7 +50,6 @@ class ADB:
self._adb_device = None # 用于存储 AdbDevice 实例
self.check_server_status()
@retry_adb
def get_adb_client(self) -> AdbClient:
"""
Returns an AdbClient instance.
@ -47,9 +58,9 @@ class ADB:
if self._adb_client is None:
try:
self.check_server_status()
self._adb_client = AdbClient("127.0.0.1", config.adb_server_port, 5)
self._adb_client = AdbClient("127.0.0.1", config.adb_server_port, 10)
except Exception as e:
raise e
raise ADBServerError(e)
return self._adb_client
@retry_adb
@ -60,9 +71,20 @@ class ADB:
"""
if self._adb_device is None:
adb_client = self.get_adb_client()
if len(adb_client.list()) == 0:
adb_client.connect(config.conf.adb, 5)
if len(devices := adb_client.list()) == 0:
try:
adb_client.connect(config.conf.adb, 10)
except Exception as e:
raise SimulatorError(e)
elif devices[0].state == "offline":
try:
adb_client.disconnect(config.conf.adb)
adb_client.connect(config.conf.adb, 10)
except Exception as e:
raise SimulatorError(e)
self._adb_device = AdbDevice(adb_client, config.conf.adb)
self.check_device_status()
return self._adb_device
@property
@ -92,9 +114,13 @@ class ADB:
Returns:
str:
"""
cmd = list(map(str, cmd))
cmd = [self.adb_bin, "-P", str(config.adb_server_port)] + cmd
return subprocess_run(cmd, timeout=timeout)
try:
cmd = list(map(str, cmd))
cmd = [self.adb_bin, "-P", str(config.adb_server_port)] + cmd
return subprocess_run(cmd, timeout=timeout)
except Exception as e:
logger.exception(e)
self.check_device_status()
def check_server_status(self) -> str:
"""Use `adb devices` as `adb start-server`, result is actually useless"""
@ -106,21 +132,11 @@ class ADB:
self.adb_command(["kill-server"])
self._adb_client = self._adb_device = None
def restart_server(self) -> None:
self.kill_server()
self.check_server_status()
def adb_disconnect(self):
self.adb_client.disconnect(config.conf.adb, raise_error=False)
self._adb_device = None
def adb_reconnect(self):
status = self.check_server_status()
if "offline" in status:
self.adb_disconnect()
else:
self.restart_server()
@retry_adb
def adb_shell(
self, cmd, stream=False, timeout=20, encoding: str | None = "utf-8", rstrip=True
):
@ -136,17 +152,28 @@ class ADB:
str if stream=False
socket if stream=True
"""
if not isinstance(cmd, str):
cmd = list(map(str, cmd))
try:
if not isinstance(cmd, str):
cmd = list(map(str, cmd))
return self.adb.shell(
cmd, stream=stream, timeout=timeout, encoding=encoding, rstrip=rstrip
)
return self.adb.shell(
cmd, stream=stream, timeout=timeout, encoding=encoding, rstrip=rstrip
)
except Exception as e:
logger.debug(cmd)
logger.exception(e)
self.check_device_status()
def adb_push(self, file_path: str, target: str):
"""push file into device with adb_bin"""
self.adb.push(file_path, target)
def check_device_status(self):
try:
self.adb.shell("echo test")
except Exception:
raise SimulatorError("设备未连接")
def process(
self, path: str, args: list[str] = [], stderr: int = subprocess.DEVNULL
) -> subprocess.Popen:
@ -259,6 +286,7 @@ class ADB:
class DIY:
@retry_adb
def capture_display():
command = config.conf.custom_screenshot.command
data = subprocess.check_output(

View file

@ -1,6 +1,5 @@
from __future__ import annotations
import functools
import socket
import threading
import time
@ -13,7 +12,6 @@ from adbutils import AdbConnection, Network
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.csleep import MowerExit
from mower.utils.device.exception import ADBError
from mower.utils.device.method.adb import ADB
from mower.utils.device.method.adb.const import KeyCode
from mower.utils.log import logger
@ -192,35 +190,6 @@ class Client:
self.control_socket.close()
self.control_socket = None
def stable(f):
@functools.wraps(f)
def inner(self: Client, *args, **kwargs):
try_count = 0
while try_count < 3:
try:
return f(self, *args, **kwargs)
except (
ConnectionResetError,
BrokenPipeError,
ConnectionAbortedError,
) as e:
logger.debug_exception(e)
self.stop()
time.sleep(1)
self.start()
try_count += 1
except Exception as e:
logger.exception(e)
self.stop()
time.sleep(1)
self.start()
try_count += 1
else:
raise ADBError("Failed to start scrcpy-server.")
return inner
@retry_scrcpy
def tap(self, x: int, y: int) -> None:
self.control.tap(x, y)