From f82543e44e7a64920c8df852693f14456d5982bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20Sonic?= Date: Thu, 22 Oct 2026 23:12:23 +0000 Subject: [PATCH] ci(android): retry UIAutomator dumps that write nothing (#64) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the loaded API 35 emulator `uiautomator dump` intermittently writes no file ("could not get idle state"). tap_label passed that straight to `cat` and failed the whole smoke on the first miss, while the launch loop already retried. The beta.16 commit failed four runs in a row this way; the identical tree passed on its PR. Only the dump is retried — crash, ANR, service and listener assertions are unchanged. Co-authored-by: babin Co-authored-by: Claude Opus 5.5 --- scripts/android_smoke.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/android_smoke.py b/scripts/android_smoke.py index 8a5067a..7ec9f41 100644 --- a/scripts/android_smoke.py +++ b/scripts/android_smoke.py @@ -37,7 +37,11 @@ def ui_dump(label): # Dump first, then read the file; never tap coordinates inferred from a # screenshot, a previous Activity, or assumed phone dimensions. adb("shell", "rm", "-f", "/sdcard/tglock-ui.xml") - adb("shell", "uiautomator", "dump", "/sdcard/tglock-ui.xml") + status = adb("shell", "uiautomator", "dump", "/sdcard/tglock-ui.xml", check=False) + if not adb("shell", "ls", "/sdcard/tglock-ui.xml", check=False).endswith("tglock-ui.xml"): + # On a loaded emulator UIAutomator intermittently reports "could not get + # idle state" and writes nothing. That is the tool, not the app. + raise subprocess.SubprocessError(f"uiautomator dump failed: {status}") text = adb("shell", "cat", "/sdcard/tglock-ui.xml") (EVIDENCE / f"{label}.xml").write_text(text, encoding="utf-8") return ET.fromstring(text) @@ -58,8 +62,12 @@ def label_node(tree, label): def tap_label(label, stage): - for attempt in range(3): - point = label_node(ui_dump(f"{stage}-{attempt}"), label) + for attempt in range(5): + try: + point = label_node(ui_dump(f"{stage}-{attempt}"), label) + except (subprocess.SubprocessError, ET.ParseError) as error: + (EVIDENCE / f"{stage}-{attempt}.error.txt").write_text(str(error), encoding="utf-8") + point = None if point is not None: adb("shell", "input", "tap", str(point[0]), str(point[1])) return