The connect takeover could only be dismissed by a session phase coming back from the
embedder, and nothing guaranteed one would. Pressing B latched "Canceling…" and waited:
- Android's console shell never sent a phase at all on the canceled path — `launch()`
returns early when `Dial.cancelled` is set — so the takeover stayed up until the app
was killed.
- The desktop shell waited for the pump's `Failed`/`Ended`, but the pump was parked
inside the blocking `NativeClient::connect*`, which had no abort. That is 15 s on a
normal dial and 185 s on a request-access connect the host holds pending approval.
Two halves, both at the point every caller routes through:
`pf-console-ui` drops the takeover itself on Back. Cancel is the user's decision and
needs no confirmation from the wire; the `CancelConnect` action still goes out, and
every embedder already handles a dial that lands afterwards (quit-close the connector,
route the end back silently). With no waiting state left to render, `Connecting.canceling`
and the "Canceling…" card go with it.
`NativeClient::connect_with_audio_format` takes an optional abort switch, polled while
the call is blocked, and the session pump passes its stop flag — so the embedder's cancel
now reaches a dial that has not landed yet instead of being answered whenever it does.
Taking it is the same give-up as running out of budget (quit close + shutdown), so the
worker stops re-dialing and the host tears down rather than lingering for a reconnect
nobody wants. Deliberately NOT aliased onto the client's own `shutdown`: the pump reads
that to mean "this connection died" and derives the session's end reason from it, which a
caller-set flag would race — a dropped link would have reported no reason at all.