Repository navigation
Give Go Wireless a 5 s tcpip timeout and settle the phone before retrying - #48
Merged
Merged
Conversation
goWireless waited for the tcpip reply with no limit, so a phone that stopped answering hung the flow. It now fails explicitly after 5 s, like handoff's limit, and leaves the USB mirror alone. Because the switch can still complete late, the serial is remembered and the next Go Wireless or handoff first waits for the phone to be back and ready. The fake adb server can stall tcpip.
…iled handoff settle() now reports waitingForPhone (and logs) while it waits, so the up to 15 s wait is not silent. A handoff whose tcpip went unanswered reports tcpipUnconfirmed instead of the untrue tcpipEnabled, and if it then ends without a wireless connection it marks the phone uncertain so the next Go Wireless or handoff settles it first.
5 tasks
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #45
What
Go Wireless now gives the phone 5 seconds to acknowledge the switch to TCP mode, fails explicitly if it does not, and makes the next Go Wireless or handoff check the phone's real state before sending anything again.
Why
WirelessManager.goWirelesswaited fortcpipwith no time limit (AdbClienthas no read timeout), so a phone or adb that stopped answering hung the flow before its 3-minute connect loop began; handoff already limits the same call to 5 s. A timeout also does not prove the switch did not happen: the phone can still switch to TCP mode late, which restarts adbd and briefly drops the USB connection.How
Decisions from the owner (2026-10-27): 5 s, explicit failure, preserve the USB mirror, account for late completion.
tcpipis wrapped in.timeout(5 s)(tcpipTimeout, injectable). On timeout the flow reportsfailedwith a plain reason ("did not answer ... It may still switch; wait for it to reconnect, then try again. The USB mirror was left as it is.") and returns null. It does not advance totcpipEnabledor the connect loop, so a timeout is never treated as success.WirelessManagerhas no access to the launcher, so the USB mirror cannot be stopped by this path.settle(serial): a no-op unless the serial is uncertain. Otherwise it pollsadb devicesuntil the phone is listed ready on two consecutive checks (so an adbd restart still in progress does not count), up to 15 s, and returns false if that does not happen.goWirelesscalls it first and fails with "the phone has not come back since the last attempt..." without sending anothertcpip. The daemon'srunHandoffcalls it too before starting a handoff.ip routeread beforetcpipalso gets the 5 s limit, since a wedged transport would otherwise hang there first; a timeout there just means no cached WiFi IP, as before.FakeAdbServer.stallTcpipReplies(bool)holdstcpiprequests and answers them when released, andtcpipRequestscounts them.settlenow reportswaitingForPhone(with the reason and the limit) throughwirelessStatus/handoffStatusand logs it, before anything else, so the up to 15 s wait is not silent; if it ends in failure the existingfailedstatus carries the reason. Protocol docs inmessages.dartlist the new stage (comment only; the UI shows stage names as received).tcpip. Handoff still carries on to the connect step after its 5 s timeout (by design, Real "connected" signal from scrcpy stdout, with retry on early exit #20), but it was reportingtcpipEnabledfor something nothing had confirmed, and if the connect step then failed nothing remembered that the phone may still switch late. Now it reportstcpipUnconfirmed("did not acknowledge ... trying to connect anyway"), and if it ends without a wireless connection after an unansweredtcpipit callsonTcpipUnconfirmed, which the daemon wires tomarkUncertain, so the next Go Wireless or handoff settles the phone first. A confirmed wireless connection settles the question, so a successful handoff is not flagged, and neither is a failed connect after an acknowledgedtcpip. The handofftcpiptimeout is now a parameter (default 5 s) so it can be tested.AdbClient(broader than this PR, tracked in A stalled adb answer hangs its caller because the adb client has no read timeout #50); the in-flight guard (goWireless is not tracked in handoffInFlight; double start is possible #19).Verified by
wireless_test.dart(6 for the timeout and retry, 3 for the visible wait andmarkUncertain) and 3 inhandoff_test.dart(unconfirmed stage and notcpipEnabled, flagged when the handoff then fails with the USB mirror left running, not flagged after an acknowledgedtcpipor a successful connection). ThewaitingForPhonetest checks it appears before any other step while the wait lasts. 6 of these are the original tests: fails within the timeout with the explicit reason and never advances (and sends exactly onetcpip); after a late completion a retry succeeds through the hotspot gateway; a retry waits while the phone is listed offline and sends nothing until it is ready; a retry fails without sending anything when the phone never returns;settleis immediate with nothing outstanding; an outright failure does not leave the serial unsettled.dart analyzeclean in core, ipc, daemon. Tests: core 27, ipc 26, daemon 88 (76 onmain) pass locally on Windows.main(with Honour ANDROID_ADB_SERVER_PORT and test the daemon failure paths against a fake adb #49) was merged into the branch first. CI results are in the checks below.runHandoff(covered only throughsettle's own tests).Risk / follow-ups
AdbClientread-timeout gap, tracked in A stalled adb answer hangs its caller because the adb client has no read timeout #50.adb devicesevery 500 ms for up to 15 s; the UI shows the new stage text but has no special treatment for it.