-
Notifications
You must be signed in to change notification settings - Fork 31
fix: WSL-only support and emulator detection #337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,7 @@ | ||||||||||||||||||||||||||||||||||||
| import json | ||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||||||||||||||
| import shlex | ||||||||||||||||||||||||||||||||||||
| import subprocess | ||||||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||||||
| from typing import Protocol | ||||||||||||||||||||||||||||||||||||
|
|
@@ -12,7 +13,7 @@ | |||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| from autowsgr.configs import UserConfig | ||||||||||||||||||||||||||||||||||||
| from autowsgr.constants.custom_exceptions import CriticalErr | ||||||||||||||||||||||||||||||||||||
| from autowsgr.types import EmulatorType | ||||||||||||||||||||||||||||||||||||
| from autowsgr.types import EmulatorType, OSType | ||||||||||||||||||||||||||||||||||||
| from autowsgr.utils.logger import Logger | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
@@ -300,3 +301,112 @@ def __get_mumu_info(self) -> dict: | |||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||
| self.logger.error(f'{cmd} {e}') | ||||||||||||||||||||||||||||||||||||
| return {} | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| class LinuxController(OSController): | ||||||||||||||||||||||||||||||||||||
| def __init__(self, config: UserConfig, logger: Logger) -> None: | ||||||||||||||||||||||||||||||||||||
| self.logger = logger | ||||||||||||||||||||||||||||||||||||
| self.is_wsl = OSType._is_wsl() | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| self.emulator_type = config.emulator_type | ||||||||||||||||||||||||||||||||||||
| if config.emulator_name is None: | ||||||||||||||||||||||||||||||||||||
| raise CriticalErr('WSL 需要显式设置 emulator_name') | ||||||||||||||||||||||||||||||||||||
| if config.emulator_start_cmd is None: | ||||||||||||||||||||||||||||||||||||
| raise CriticalErr('WSL 需要显式设置 emulator_start_cmd') | ||||||||||||||||||||||||||||||||||||
| if config.emulator_process_name is None: | ||||||||||||||||||||||||||||||||||||
| raise CriticalErr('WSL 需要显式设置 emulator_process_name') | ||||||||||||||||||||||||||||||||||||
| self.emulator_name = config.emulator_name | ||||||||||||||||||||||||||||||||||||
| self.emulator_start_cmd = config.emulator_start_cmd | ||||||||||||||||||||||||||||||||||||
| self.emulator_process_name = config.emulator_process_name | ||||||||||||||||||||||||||||||||||||
| self.dev_name = f'Android:///{self.emulator_name}' | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| def is_android_online(self) -> bool: | ||||||||||||||||||||||||||||||||||||
| """判断 timer 给定的设备是否在线""" | ||||||||||||||||||||||||||||||||||||
| devices = self._adb_devices() | ||||||||||||||||||||||||||||||||||||
| if self.emulator_name in devices: | ||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||
| if self.is_wsl: | ||||||||||||||||||||||||||||||||||||
| return self._is_windows_process_running() | ||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||
| subprocess.run( | ||||||||||||||||||||||||||||||||||||
| ['pgrep', '-f', self.emulator_process_name], | ||||||||||||||||||||||||||||||||||||
| check=True, | ||||||||||||||||||||||||||||||||||||
| stdout=subprocess.DEVNULL, | ||||||||||||||||||||||||||||||||||||
| stderr=subprocess.DEVNULL, | ||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||
| except subprocess.CalledProcessError: | ||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| def kill_android(self) -> None: | ||||||||||||||||||||||||||||||||||||
| """强制终止模拟器进程""" | ||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||
| if self.is_wsl: | ||||||||||||||||||||||||||||||||||||
| result = subprocess.run( | ||||||||||||||||||||||||||||||||||||
| ['taskkill.exe', '/f', '/im', self.emulator_process_name], | ||||||||||||||||||||||||||||||||||||
| capture_output=True, | ||||||||||||||||||||||||||||||||||||
| text=True, | ||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||
| if result.returncode != 0: | ||||||||||||||||||||||||||||||||||||
| raise CriticalErr(result.stderr.strip() or result.stdout.strip()) | ||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||
| subprocess.run( | ||||||||||||||||||||||||||||||||||||
| ['pkill', '-9', '-f', self.emulator_process_name], | ||||||||||||||||||||||||||||||||||||
| check=True, | ||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+353
to
+356
|
||||||||||||||||||||||||||||||||||||
| subprocess.run( | |
| ['pkill', '-9', '-f', self.emulator_process_name], | |
| check=True, | |
| ) | |
| try: | |
| subprocess.run( | |
| ['pkill', '-9', '-f', self.emulator_process_name], | |
| check=True, | |
| ) | |
| except subprocess.CalledProcessError as e: | |
| # pkill 返回 1 表示未找到匹配进程,这种情况不视为错误 | |
| if e.returncode == 1: | |
| self.logger.info( | |
| f'未找到需要终止的模拟器进程: {self.emulator_process_name}' | |
| ) | |
| else: | |
| raise |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -46,7 +46,7 @@ class OcrBackend(StrEnum): | |||||||||||
|
|
||||||||||||
| class OSType(StrEnum): | ||||||||||||
| windows = 'Windows' | ||||||||||||
| linux = 'Linux' | ||||||||||||
| linux = 'linux' | ||||||||||||
| macos = 'macOS' | ||||||||||||
|
|
||||||||||||
| @classmethod | ||||||||||||
|
|
@@ -55,8 +55,25 @@ def auto(cls) -> 'OSType': | |||||||||||
| return OSType.windows | ||||||||||||
| if sys.platform == 'darwin': | ||||||||||||
| return OSType.macos | ||||||||||||
| if sys.platform.startswith('linux'): | ||||||||||||
| if cls._is_wsl(): | ||||||||||||
| return OSType.linux | ||||||||||||
|
Comment on lines
+59
to
+60
|
||||||||||||
| if cls._is_wsl(): | |
| return OSType.linux | |
| # 在 WSL 环境下,当前仍复用 Windows 的实现,返回 OSType.windows | |
| if cls._is_wsl(): | |
| return OSType.windows |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WSL 分支中 taskkill.exe 返回非 0 时直接抛 CriticalErr,会导致“模拟器未运行/已退出”时 kill_android 失败,从而让 connect_android() 的 restart_android() 在首次启动或进程已退出时无法继续。建议将“未找到进程/没有任务匹配”这类返回视为可忽略(例如检查 stderr/stdout 中的典型提示或 returncode),仅在真正的执行错误时才抛错。