diff --git a/tests/mobile/cdp.mjs b/tests/mobile/cdp.mjs index df448af..c9cb0ec 100644 --- a/tests/mobile/cdp.mjs +++ b/tests/mobile/cdp.mjs @@ -94,12 +94,30 @@ export async function attachPhone(port) { throw new Error("the phone is in use (" + who + " is on screen); not touching it"); } } - const pid = adb("shell", "pidof", "com.soulstream.app").toString().trim(); + /* The devtools socket is registered by the WebView, not by the process, so + there is a window after a launch where the app is up, focused and has a + pid, and the socket does not exist yet. On a loaded machine that window + has been as long as ten seconds — a walk that attached once and gave up + read it as "is SoulStream on screen?" when it plainly was. Try for a + while, re-reading the pid each time in case the app restarted under us. */ + let pid = ""; + let last = null; + for (let attempt = 0; attempt < 6; attempt++) { + pid = adb("shell", "pidof", "com.soulstream.app").toString().trim(); + if (pid) { + adb("forward", "--remove-all"); + adb("forward", `tcp:${port}`, `localabstract:webview_devtools_remote_${pid}`); + try { + const cdp = await CDP.attach(port, { phone: true }); + return { cdp, pid }; + } catch (e) { + last = e; + } + } + await sleep(2500); + } if (!pid) throw new Error("SoulStream is not running on the phone (adb shell pidof found nothing)"); - adb("forward", "--remove-all"); - adb("forward", `tcp:${port}`, `localabstract:webview_devtools_remote_${pid}`); - const cdp = await CDP.attach(port, { phone: true }); - return { cdp, pid }; + throw last ?? new Error("could not attach to the phone's WebView on port " + port); } /** The phone's own frame, status bar included. */