Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ProtonVPN/android-app/llms.txt
Use this file to discover all available pages before exploring further.
VPN connection flow
When the user taps Connect, the following sequence runs synchronously through the layered architecture before the tunnel is active and the UI reflects the new state.User triggers a ConnectIntent
The UI creates an The composable delegates through a
AnyConnectIntent value and passes it to VpnConnectionManager.connect. ConnectIntent is a sealed interface that captures the user’s intent without yet resolving a specific server:VpnConnect function interface, which VpnConnectionManager implements.VpnConnectionManager processes the intent
VpnConnectionManager (vpn/VpnConnectionManager.kt) is the central coordinator. It holds the internal connection state machine:Server selection
ServerManager2.getBestServerForConnectIntent resolves the intent to a concrete Server object. It delegates to ServerManager.getServerForProfile which walks the in-memory server list applying filters for:- User’s subscription tier (free vs. paid servers)
- Excluded locations (split-tunneling exclusions from
ExcludedLocations) - Server load and maintenance status
- Required
ServerFeatureflags (Secure Core, P2P, streaming, etc.)
Protocol negotiation and port scanning
ProtonVpnBackendProvider.prepareConnection is called with the resolved server and the user’s ProtocolSelection. For WireGuard it probes available ports on the server to find an open one:PrepareResult holding the chosen VpnBackend and the fully-populated ConnectionParams.Certificate acquisition
Before opening the tunnel, each backend needs a valid client certificate. The certificate contains the session’s public key signed by Proton. It is passed to the local agent alongside the private key PEM so the agent can open an mTLS connection to the VPN server.
CertificateRepository.getCertificate returns the locally cached certificate if it has not expired; otherwise it fetches a fresh one from the API:Backend starts the VPN tunnel
VpnBackend.connect(connectionParams) is called on the selected backend.WireGuard path:VPN service starts
For WireGuard, the OS
VpnService (WireguardWrapperService) is started as a foreground service when the GoBackend sets the tunnel to UP. The service holds the VPN interface file descriptor. WireguardBackend keeps a weak reference to it via serviceCreated / serviceDestroyed callbacks.Android requires a foreground service notification while the VPN tunnel is active. The notification is managed by the VPN service, not the backend.
VpnStateMonitor emits state updates
VpnConnectionManager observes each backend’s selfStateFlow and forwards changes to VpnStateMonitor:UI observes state via StateFlow
ViewModels collect
VpnStateMonitor.status (or the UI-filtered VpnStatusProviderUI.uiStatus) and map it to composable-friendly UI state. Compose recomposes only the affected parts of the tree when the state changes.VpnStatusProviderUI wraps the monitor and filters out internal GuestHole connections so they are never surfaced in the main UI.Server list data flow
The server list follows a separate path from API through storage to the UI.ServerListUpdaterperiodically calls the Proton API and saves the raw server list viaServersStoreto a file (servers.store) in the app’s files directory.ServerManagerloads the file on demand (ensureLoaded), parses it intoVpnCountry/Serverobjects, and keeps them in memory. It exposes aserverListVersionStateFlowthat increments on each reload.ServerManager2is a thin suspending wrapper that callsserverManager.ensureLoaded()before delegating. New code should useServerManager2rather thanServerManagerdirectly.- ViewModels collect
serverListVersion-derived flows (e.g.,allServersFlow,allServersByScoreFlow) and map them to their own UI state.
Settings propagation
User settings flow from storage to the active VPN backend throughSettingsForConnection.
SettingsForConnection merges base settings with per-connection overrides (SettingsOverrides) from the active ConnectIntent. The backend listens for changes:
Error and fallback flow
When a backend emits an error state,VpnConnectionManager decides whether to recover or surface the failure.
VpnConnectionErrorHandler, which pings candidate servers and returns either a Switch result (connect to the new server) or an Error result. The manager then either initiates a seamless server switch or disconnects and notifies the user.