Skip to content

Session State and Events

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

Session State and Events

中文 · Runtime Main Path

The session runtime uses three information layers to express where the session is, what just happened, and where each component ended up. They serve different purposes and must not be collapsed into one boolean or derived from logs.

Three-layer model

Layer Type Question Main consumers
Main state SessionState Which overall phase is the session in? UI and lifecycle decisions
Process facts SessionEvent Which step just succeeded, failed, or requested an action? Session handlers, log and monitoring projections
Component snapshot SessionComponentStateSnapshot What is the current state of ADB, server, sockets, and decoders? Diagnostics and readiness checks

Session.handleEvent() writes events to one Channel. The session processes them sequentially and updates SessionRuntimeState. Producers must not bypass this entry point to create competing global session state.

Main state

SessionState currently contains:

  • Idle
  • AdbConnecting
  • AdbConnected(context)
  • AdbDisconnected(issue)
  • ServerStarting
  • ServerStarted(context)
  • ServerFailed(issue)
  • Connected(context)
  • Reconnecting(context)
  • Failed(issue)

These are runtime phases, not a promise that every branch follows one linear graph. The Connected context records the local port, connected sockets, whether audio is enabled, and whether the dummy byte was confirmed. It means the socket layer reached its working condition; by itself it does not prove that metadata or a decoder is ready.

Event domains

SessionEvent is grouped by responsibility:

  • ADB: connecting, verification, success, and disconnection.
  • Server: push, startup, and their failures.
  • Forward: setup, removal, and failure.
  • Socket: connecting, connected, disconnected, and error.
  • Decoder: started, stopped, and error.
  • Control: RequestReconnect and RequestCleanup, which are runtime action requests.
  • Codec: video/audio encoder detection and errors.
  • Session: SessionError for failures that do not belong to a more specific domain.

Events should carry structured contexts or issues. UI text and logs can be generated from them, but failures should not be flattened into unclassifiable strings at the source.

Component snapshot

Tracked SessionComponent values are the ADB connection, scrcpy server, video/audio/control sockets, and video/audio decoders. Each uses ComponentState: Idle, Starting, Running, Connected, Stopped, Disconnected, or Error(message).

The snapshot derives three read models:

  • InfrastructureConnectionReadModel: whether ADB is connected, the server is running, and socket prerequisites are met.
  • SocketConnectionReadModel: expected socket count, connected set, video readiness, and whether all required sockets are present.
  • DecoderConnectionReadModel: running and stopped decoder sets.

When audio is disabled, runtime state updates the expected socket count; consumers must not continue assuming three sockets.

Events to state

  • Events are input facts or action requests; main state and component snapshots are read models produced by event handling.
  • Events such as AdbConnected, ServerStarted, and SocketConnected advance main or component state.
  • RequestReconnect increments the attempt and invokes the single callback only when the session is neither reconnecting nor failed and budget remains.
  • Entering Connected resets the reconnect counter. RequestCleanup returns the main state to Idle and clears component state.
  • A decoder size error may lower maxSize for the current run and request reconnection, but that temporary fallback is not written to persisted user configuration.

Issue classification

Issue models are divided into ADB, server, forward, socket, decoder, reconnect, codec, and session domains. Place new failures in the nearest infrastructure domain and preserve structured fields needed by policy and presentation. Use a session issue only for genuinely cross-domain failures.

Debugging order

  1. Find the phase where SessionState stopped.
  2. Find the last relevant SessionEvent and its context or issue.
  3. Identify the component that did not reach its expected state in the snapshot.
  4. Then follow that component's code and logs instead of guessing state from the complete log stream.

Change checklist

  • Does a new event have a clear producer, one handling entry point, and an issue domain?
  • Should it change main state, component state, or only a monitoring projection?
  • Does the UI incorrectly treat ADB, socket, and media readiness as the same state?
  • Can cleanup and reconnection both react to the same low-level closure?
  • Do tests cover success, failure, duplicate events, and audio-disabled paths?

Clone this wiki locally