Merge pull request #973 from SaiCateDoan/wsa

Add: WSA solution on display 0 (experimental) Ver 2
This commit is contained in:
LmeSzinc 2022-03-18 21:37:57 +08:00 committed by GitHub
commit 1e4d1a3187
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 147 additions and 10 deletions

View File

@ -32,7 +32,7 @@ class AdbManager(DeployConfig):
init.install()
except AssertionError:
print(f'AssertionError when installing uiautomator2 on device {device.serial}')
print('If you are using BlueStacks or LD player, '
print('If you are using BlueStacks or LD player or WSA, '
'please enable ADB in the settings of your emulator')
init._device.shell(["rm", "/data/local/tmp/minicap"])
init._device.shell(["rm", "/data/local/tmp/minicap.so"])

View File

@ -276,7 +276,7 @@
},
"Serial": {
"name": "Serial",
"help": "Default serial for select emulators:\n- BlueStacks 127.0.0.1:5555\n- BlueStacks4 Hyper-V use \"bluestacks4-hyperv\", \"bluestacks4-hyperv-2\" for multi instance, and so on\n- BlueStacks5 Hyper-V use \"bluestacks5-hyperv\", \"bluestacks5-hyperv-1\" for multi instance, and so on\n- NoxPlayer 127.0.0.1:62001\n- NoxPlayer64bit 127.0.0.1:59865\n- MuMuPlayer 127.0.0.1:7555\n- MemuPlayer 127.0.0.1:21503\n- LDPlayer emulator-5554 or 127.0.0.1:5555\nIf there are multiple emulator instances running, the default is reserved for one of them and the others will use different serials to avoid conflicts\nOpen console.bat and run `adb devices` to find what they are"
"help": "Default serial for select emulators:\n- BlueStacks 127.0.0.1:5555\n- BlueStacks4 Hyper-V use \"bluestacks4-hyperv\", \"bluestacks4-hyperv-2\" for multi instance, and so on\n- BlueStacks5 Hyper-V use \"bluestacks5-hyperv\", \"bluestacks5-hyperv-1\" for multi instance, and so on\n- NoxPlayer 127.0.0.1:62001\n- NoxPlayer64bit 127.0.0.1:59865\n- MuMuPlayer 127.0.0.1:7555\n- MemuPlayer 127.0.0.1:21503\n- LDPlayer emulator-5554 or 127.0.0.1:5555\n- WSA use \"wsa-0\" to make the game run in the background, which needs to be controlled or closed by third-party software\nIf there are multiple emulator instances running, the default is reserved for one of them and the others will use different serials to avoid conflicts\nOpen console.bat and run `adb devices` to find what they are"
},
"PackageName": {
"name": "Package Name",

View File

@ -276,7 +276,7 @@
},
"Serial": {
"name": "模拟器 Serial",
"help": "模拟器默认 Serial\n- 蓝叠模拟器 127.0.0.1:5555\n- 蓝叠模拟器4 Hyper-v版填\"bluestacks4-hyperv\"自动连接,多开填\"bluestacks4-hyperv-2\"以此类推\n- 蓝叠模拟器5 Hyper-v版填\"bluestacks5-hyperv\"自动连接,多开填\"bluestacks5-hyperv-1\"以此类推\n- 夜神模拟器 127.0.0.1:62001\n- 夜神模拟器64位 127.0.0.1:59865\n- MuMu模拟器 127.0.0.1:7555\n- 逍遥模拟器 127.0.0.1:21503\n- 雷电模拟器 emulator-5554 或 127.0.0.1:5555\n如果你有多个模拟器,它们的 Serial 将不是默认的,可以在 console.bat 中执行 `adb devices` 查询"
"help": "模拟器默认 Serial\n- 蓝叠模拟器 127.0.0.1:5555\n- 蓝叠模拟器4 Hyper-v版填\"bluestacks4-hyperv\"自动连接,多开填\"bluestacks4-hyperv-2\"以此类推\n- 蓝叠模拟器5 Hyper-v版填\"bluestacks5-hyperv\"自动连接,多开填\"bluestacks5-hyperv-1\"以此类推\n- 夜神模拟器 127.0.0.1:62001\n- 夜神模拟器64位 127.0.0.1:59865\n- MuMu模拟器 127.0.0.1:7555\n- 逍遥模拟器 127.0.0.1:21503\n- 雷电模拟器 emulator-5554 或 127.0.0.1:5555\n- WSA填\"wsa-0\"使游戏在后台运行需要使用第三方软件操控或关闭建议使用scrcpy操控\n如果你有多个模拟器,它们的 Serial 将不是默认的,可以在 console.bat 中执行 `adb devices` 查询"
},
"PackageName": {
"name": "游戏包名",

View File

@ -276,7 +276,7 @@
},
"Serial": {
"name": "模擬器 Serial",
"help": "模擬器預設 Serial\n- 藍疊模擬器 127.0.0.1:5555\n- 藍疊模擬器4 Hyper-v版填\"bluestacks4-hyperv\"自動連接,多開填\"bluestacks4-hyperv-2\"以此類推\n- 藍疊模擬器5 Hyper-v版填\"bluestacks5-hyperv\"自動連接,多開填\"bluestacks5-hyperv-1\"以此類推\n- 夜神模擬器 127.0.0.1:62001\n- 夜神模擬器64位元 127.0.0.1:59865\n- MuMu模擬器 127.0.0.1:7555\n- 逍遙模擬器 127.0.0.1:21503\n- 雷電模擬器 emulator-5554 或 127.0.0.1:5555\n如果你有多個模擬器,他們的 Serial 將不是預設的,可以在 console.bat 中執行 `adb devices` 查詢"
"help": "模擬器預設 Serial\n- 藍疊模擬器 127.0.0.1:5555\n- 藍疊模擬器4 Hyper-v版填\"bluestacks4-hyperv\"自動連接,多開填\"bluestacks4-hyperv-2\"以此類推\n- 藍疊模擬器5 Hyper-v版填\"bluestacks5-hyperv\"自動連接,多開填\"bluestacks5-hyperv-1\"以此類推\n- 夜神模擬器 127.0.0.1:62001\n- 夜神模擬器64位元 127.0.0.1:59865\n- MuMu模擬器 127.0.0.1:7555\n- 逍遙模擬器 127.0.0.1:21503\n- 雷電模擬器 emulator-5554 或 127.0.0.1:5555\n- WSA填\"wsa-0\"使遊戲在後臺運行,需要使用第三方軟件操控或關閉\n如果你有多個模擬器,他們的 Serial 將不是預設的,可以在 console.bat 中執行 `adb devices` 查詢"
},
"PackageName": {
"name": "遊戲檔名",

View File

@ -1,12 +1,13 @@
from lxml import etree
from module.device.method.adb import Adb
from module.device.method.wsa import WSA
from module.device.method.uiautomator_2 import Uiautomator2
from module.device.method.utils import HierarchyButton
from module.logger import logger
class AppControl(Adb, Uiautomator2):
class AppControl(Adb, WSA, Uiautomator2):
hierarchy: etree._Element
def app_is_running(self) -> bool:
@ -25,7 +26,9 @@ class AppControl(Adb, Uiautomator2):
package = self.config.Emulator_PackageName
method = self.config.Emulator_ControlMethod
logger.info(f'App start: {package}')
if method == 'uiautomator2' or method == 'minitouch':
if self.config.Emulator_Serial == 'wsa-0':
self.app_start_wsa(package, display = 0)
elif method == 'uiautomator2' or method == 'minitouch':
self.app_start_uiautomator2(package)
else:
self.app_start_adb(package)

View File

@ -36,6 +36,8 @@ class Connection:
self.serial = self.find_bluestacks4_hyperv(self.serial)
if "bluestacks5-hyperv" in self.serial:
self.serial = self.find_bluestacks5_hyperv(self.serial)
if "wsa" in self.serial:
self.serial = '127.0.0.1:58526'
logger.attr('Adb_binary', self.adb_binary)

View File

@ -67,7 +67,7 @@ def retry(func):
except AssertionError as e:
logger.exception(e)
possible_reasons(
'If you are using BlueStacks or LD player, '
'If you are using BlueStacks or LD player or WSA, '
'please enable ADB in the settings of your emulator'
)
break

View File

@ -76,7 +76,7 @@ def handle_adb_error(e):
# AdbError()
logger.exception(e)
possible_reasons(
'If you are using BlueStacks or LD player, please enable ADB in the settings of your emulator',
'If you are using BlueStacks or LD player or WSA, please enable ADB in the settings of your emulator',
'Emulator died, please restart emulator',
'Serial incorrect, no such device exists or emulator is not running'
)

119
module/device/method/wsa.py Normal file
View File

@ -0,0 +1,119 @@
import re
from adbutils.errors import AdbError
from module.device.connection import Connection
from module.device.method.utils import possible_reasons, handle_adb_error, RETRY_TRIES, RETRY_DELAY
from module.exception import RequestHumanTakeover
from module.logger import logger
def retry(func):
def retry_wrapper(self, *args, **kwargs):
"""
Args:
self (Adb):
"""
init = None
for _ in range(RETRY_TRIES):
try:
if callable(init):
self.sleep(RETRY_DELAY)
init()
return func(self, *args, **kwargs)
# Can't handle
except RequestHumanTakeover:
break
# When adb server was killed
except ConnectionResetError as e:
logger.error(e)
def init():
self.adb_disconnect(self.serial)
self.adb_connect(self.serial)
# AdbError
except AdbError as e:
if handle_adb_error(e):
def init():
self.adb_disconnect(self.serial)
self.adb_connect(self.serial)
else:
break
# Unknown, probably a trucked image
except Exception as e:
logger.exception(e)
def init():
pass
logger.critical(f'Retry {func.__name__}() failed')
raise RequestHumanTakeover
return retry_wrapper
class WSA(Connection):
@retry
def app_start_wsa(self, package_name, display, allow_failure=False):
"""
Args:
package_name (str):
display (int):
allow_failure (bool):
Returns:
bool: If success to start
"""
self.adb_shell(['svc', 'power', 'stayon', 'true'])
activity_name = self.get_main_activity_name(package_name=package_name)
result = self.adb_shell(
['am', 'start', '--display', display, package_name +
'/' + activity_name])
if 'No activities found' in result:
# ** No activities found to run, monkey aborted.
if allow_failure:
return False
else:
logger.error(result)
possible_reasons(f'"{package_name}" not found, please check setting Emulator.PackageName')
raise RequestHumanTakeover
else:
# Events injected: 1
# ## Network stats: elapsed time=4ms (0ms mobile, 0ms wifi, 4ms not connected)
return True
@retry
def get_main_activity_name(self, package_name):
try:
output = self.adb_shell(['dumpsys', 'package', package_name])
_activityRE = re.compile(
r'\w+ ' + package_name + r'/(?P<activity>[^/\s]+) filter'
)
ms = _activityRE.finditer(output)
ret = next(ms).group('activity')
return ret
except StopIteration:
logger.critical("Couldn't get activity name, please check setting Emulator.PackageName")
raise RequestHumanTakeover
@retry
def get_display_id(self):
"""
Returns:
0: Could not find
int: Display id of the game
"""
try:
get_dump_sys_display = str(self.adb_shell(['dumpsys', 'display']))
display_id_list = re.findall(r'systemapp:' + self.config.Emulator_PackageName + ':' + '(.+?)', get_dump_sys_display, re.S)
display_id = int(display_id_list[0])
return display_id
except IndexError:
return 0 # When game running on display 0, its display id could not be found
@retry
def display_resize_wsa(self, display):
logger.warning('display ' + str(display) + ' should be resized')
self.adb_shell(['wm', 'size', '1280x720', '-d', str(display)])

View File

@ -11,13 +11,14 @@ from module.base.decorator import cached_property
from module.base.timer import Timer, timer
from module.base.utils import get_color, save_image, limit_in
from module.device.method.adb import Adb
from module.device.method.wsa import WSA
from module.device.method.ascreencap import AScreenCap
from module.device.method.uiautomator_2 import Uiautomator2
from module.exception import RequestHumanTakeover, ScriptError
from module.logger import logger
class Screenshot(Adb, Uiautomator2, AScreenCap):
class Screenshot(Adb, WSA, Uiautomator2, AScreenCap):
_screen_size_checked = False
_screen_black_checked = False
_minicap_uninstalled = False
@ -178,6 +179,9 @@ class Screenshot(Adb, Uiautomator2, AScreenCap):
self.image = self._handle_orientated_image(self.image)
orientated = True
continue
elif self.config.Emulator_Serial == 'wsa-0':
self.display_resize_wsa(0)
return False
elif hasattr(self, 'app_is_running') and not self.app_is_running():
logger.warning('Received orientated screenshot, game not running')
return True
@ -193,7 +197,16 @@ class Screenshot(Adb, Uiautomator2, AScreenCap):
# May get a pure black screenshot on some emulators.
color = get_color(self.image, area=(0, 0, 1280, 720))
if sum(color) < 1:
if self.config.Emulator_ScreenshotMethod == 'uiautomator2':
if self.config.Emulator_Serial == 'wsa-0':
for _ in range(2):
display = self.get_display_id()
if display == 0:
return True
logger.info(f'Game running on display {display}')
logger.warning('Game not running on display 0, will be restarted')
self.app_stop_uiautomator2(self.config.Emulator_PackageName)
return False
elif self.config.Emulator_ScreenshotMethod == 'uiautomator2':
logger.warning(f'Received pure black screenshots from emulator, color: {color}')
logger.warning('Uninstall minicap and retry')
self.uninstall_minicap()