Skip to content

ADB Connection Lifecycle

星冉 edited this page Jul 21, 2026 · 1 revision

ADB Connection Lifecycle

中文 · ADB, USB, and Wireless

This page defines responsibilities among the ADB connection pool, primary and streaming lanes, foreground heartbeat, and scrcpy health monitoring. The former model in which scrcpy and management took over a connection based on a delayed-ACK profile is obsolete. A current network AdbConnection manages purpose-specific lanes internally.

Ownership

Component Responsibility
AdbConnectionManager Unified TCP/mDNS/USB APIs, per-device locking, registry, and USB detach
AdbConnectionConnector Create and verify a DadbSession, warm its optional streaming route, and construct AdbConnection
AdbConnectionRegistry Current device-id-to-connection object and connected-device flow
AdbConnection Commands, shell and streams, forwarding, device information, and lane lifecycle
ScrcpyServiceHeartbeatMonitor Check protected transports every 15 seconds and rebuild the same exact identity
ConnectionHealthMonitor Observe current scrcpy video/audio/control sockets without rebuilding the ADB registry

AdbConnectionManager does not run another periodic global keepalive. scrcpy socket health and foreground-service ADB heartbeat observe different data planes.

Connection and reuse

  • TCP and mDNS operations lock by transport device id. An existing object is verified and reused on success; verification failure or forced reconnect closes and replaces it.
  • USB also locks by normalized usb:<serial> and verifies reuse. Permission and system UsbDevice lifetime remain in the USB path.
  • Once a candidate race selects a winner, the session, server, monitoring, and cleanup must hold the same AdbConnection object.
  • Prefer conditional disconnectDeviceIfCurrent during removal so an old heartbeat result cannot close a newly replaced object.

Primary and streaming lanes

The network connector creates a DadbSession with an immediately available primary Dadb using withDelayedAck=false. After primary verification succeeds, it warms one background streaming route whose Dadb uses withDelayedAck=true. Concurrent callers of DadbSession.route(STREAMING) share that creation attempt; a failed attempt can be retried without closing the primary route. Closing the logical session releases both physical connections. USB is exclusive, so its DadbSession has one Dadb and maps both routes to that same transport.

AdbConnection keeps ordinary commands, management shell, file/helper work, and ordinary TCP port forwarding on the primary route. scrcpy server upload/start, localabstract sockets, scrcpy forwarding, and remote encoder detection request the streaming route. Streaming forward state has its own registry so closing or replacing one lane does not lose ownership of the other lane's forwards.

Consequences:

  • Delayed ACK is a lane or negotiated capability, no longer a pair of mutually exclusive “remote” and “management” product profiles.
  • supportsDelayedAck() reports delayed-ACK support only after the streaming route is ready; it must not block to create the route or infer screen ownership.
  • Ordinary and streaming work must call the matching API. A one-shot management command does not create the secondary lane, while scrcpy waits for the shared warmed route when it reaches a streaming operation.

Foreground heartbeat

The foreground service checks only exact registered protected transport identities. If a connection is absent or isConnected() is false, it parses the original device id and rebuilds through the corresponding USB, mDNS, or TCP API. The returned device id must match; otherwise the unexpected connection is closed and the attempt fails.

Devices are checked concurrently within a round, but removal compares both the ProtectedAdbDevice and expected AdbConnection object so an old asynchronous result cannot remove updated state. Persistently failed entries are removed from the protected set.

Boundary with scrcpy

  • ADB heartbeat answers whether the transport remains usable.
  • The scrcpy health monitor answers whether the current media and control sockets remain alive.
  • If ADB is healthy but a socket failed, rebuild the scrcpy path without first destroying the healthy transport.
  • Hard signals such as USB detach clear the registry and publish disconnect events first; heartbeat is only a fallback.
  • Socket closure caused by explicit stop must not be interpreted as a new reconnect request.

Change and regression checks

  • Check device-id locking and conditional removal for connection-replacement races.
  • Network primary verification must complete before the streaming route is warmed; both routes keep the same endpoint and logical-session owner.
  • A protected transport must rebuild with its original TCP, USB, or mDNS identity.
  • Run dadb DadbSessionTest, app ConnectionSocketOrderTest, and ScrcpyServiceHeartbeatMonitorTest, plus device tests for USB detach, network loss/recovery, and delayed-ACK route setup.

Clone this wiki locally