Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions node_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from Framework.install_handler.android.java import update_java_path
from settings import ZEUZ_NODE_PRIVATE_RSA_KEYS_DIR
from Framework.install_handler.long_poll_handler import InstallHandler
from server.mobile import upload_android_ui_dump, upload_ios_ui_dump
from server.mobile import start_ui_dump_uploads
from Framework.install_handler.android.android_sdk import update_android_sdk_path

def adjust_python_path():
Expand Down Expand Up @@ -1347,8 +1347,7 @@ async def main():
update_android_sdk_path()
update_outdated_modules()
asyncio.create_task(start_server())
asyncio.create_task(upload_android_ui_dump())
asyncio.create_task(upload_ios_ui_dump())
start_ui_dump_uploads()
asyncio.create_task(delete_old_automationlog_folders())
await destroy_session()

Expand Down
6 changes: 5 additions & 1 deletion server/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from server.connect import router as connect_router
from server.evaluator import router as evaluator_router
from server.node_operator import router as operator_router
from server.mobile import router as mobile_router, upload_android_ui_dump
from server.mobile import router as mobile_router, start_ui_dump_uploads
from server.mac import router as mac_router
from server.linux import router as linux_router
from server.installers import router as installers_router
Expand Down Expand Up @@ -45,6 +45,10 @@ def main() -> FastAPI:
v1router.include_router(linux_router)
v1router.include_router(installers_router)
app = FastAPI()

@app.on_event("startup")
async def _start_background_uploads():
start_ui_dump_uploads()
app.include_router(v1router)

origins = [
Expand Down
77 changes: 50 additions & 27 deletions server/mobile.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@

router = APIRouter(prefix="/mobile", tags=["mobile"])

_UPLOAD_TASKS_STARTED = False


def start_ui_dump_uploads() -> None:
"""Start background UI dump uploads once per process."""
global _UPLOAD_TASKS_STARTED
if _UPLOAD_TASKS_STARTED:
return
_UPLOAD_TASKS_STARTED = True
asyncio.create_task(upload_android_ui_dump())
asyncio.create_task(upload_ios_ui_dump())


def is_wda_running(port: int) -> bool:
"""Check if WebDriverAgent is running on given port."""
Expand Down Expand Up @@ -332,26 +344,35 @@

def capture_ui_dump(device_serial: str | None = None):
"""Capture the current UI hierarchy from the device"""
# Try to get from active Appium driver first (like web does)
try:
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import appium_driver

if appium_driver is not None:
page_src = appium_driver.page_source
with open(UI_XML_PATH, "w") as xml_file:
xml_file.write(page_src)
return
except Exception as e:
pass

# Fallback to ADB
device_flag = f"-s {device_serial}" if device_serial else ""

if os.path.exists(UI_XML_PATH):
os.remove(UI_XML_PATH)

out = run_adb_command(
f"{ADB_PATH} {device_flag} shell uiautomator dump /sdcard/ui.xml".strip()
)
if out.startswith("Error:"):
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import (
appium_driver,
)

if appium_driver is None:
return
page_src = appium_driver.page_source
with open(UI_XML_PATH, "w") as xml_file:
xml_file.write(page_src)
else:
out = run_adb_command(
f"{ADB_PATH} {device_flag} pull /sdcard/ui.xml {UI_XML_PATH}"
)
if out.startswith("Error:"):
return
return

out = run_adb_command(
f"{ADB_PATH} {device_flag} pull /sdcard/ui.xml {UI_XML_PATH}"
)
if os.path.exists(UI_XML_PATH):
size = os.path.getsize(UI_XML_PATH)


def capture_screenshot(device_serial: str | None = None):
Expand Down Expand Up @@ -444,6 +465,19 @@


def capture_ios_ui_dump(device_udid: str):
# Try to get from active Appium driver first (like web does)
try:
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import appium_driver

if appium_driver is not None:
page_src = appium_driver.page_source
with open(IOS_XML_PATH, 'w', encoding='utf-8') as xml_file:
xml_file.write(page_src)
return
except Exception as e:
pass

# Fallback to WDA
real_hierarchy = get_real_ios_hierarchy(device_udid)
if real_hierarchy:
try:
Expand All @@ -456,17 +490,6 @@
with open(IOS_XML_PATH, 'w', encoding='utf-8') as xml_file:
xml_file.write(xml_content)
return

# Fallback to Appium driver
try:
from Framework.Built_In_Automation.Mobile.CrossPlatform.Appium.BuiltInFunctions import appium_driver
if appium_driver is not None:
page_src = appium_driver.page_source
with open(IOS_XML_PATH, 'w', encoding='utf-8') as xml_file:
xml_file.write(page_src)
return
except:
pass


async def upload_android_ui_dump():
Expand Down Expand Up @@ -778,4 +801,4 @@

return {"installed": False}
except Exception as e:
return {"installed": False, "error": str(e)}
return {"installed": False, "error": str(e)}
Loading