VPN Icon Says Connected: What It Really Tells You
A connected icon may only mean one app tunnel or one probe succeeded. Define the scope, treat stale readings as unknown, and keep blocking separate.
A green VPN icon is a claim about something, and the useful question is what. On a phone it may reflect one client's tunnel, the transport of the current network, or a single successful request to an internal page. Those observations come from different sources, refresh at different rates, and can disagree on the same screen. That is why an icon can look healthy while the browser in front of you fails.
Pin the scope before reading the colour, or the colour will answer a question nobody asked.
The Icon Answers a Narrower Question Than You Think
Start with one declared scope, such as the personal browser using the approved personal tunnel. A work-profile tunnel does not answer that question for a personal app, and a per-app VPN configuration may exclude the very browser you are testing. A local filtering client can show connected while sending nothing to a remote gateway, because its tunnel terminates on the device.
On Android, the network callbacks behind an indicator report transports and capabilities for a network. A VPN transport says which network carries traffic, not which applications or address families use it.
Build the State Table From Evidence
Three or four states are enough if each one names the evidence behind it. The columns below start from what can be observed rather than from the colour you want to show, which keeps a stale reading from becoming a success claim.
| Signal actually observed | What it establishes | What remains open |
|---|---|---|
| Target client reports an established tunnel | That client believes its tunnel is up, within its own scope | Other apps, other profiles, other address families |
| Active network exposes a VPN transport | Some tunnel carries the current network | Which app it belongs to and where it exits |
| Probe to a private host returned fresh data | One request reached one destination at one time | Everything the probe does not touch |
| Callbacks stopped or data is older than the refresh window | Nothing current is known | Any statement about the tunnel state |
The last row is the one that gets dropped in practice. An indicator that keeps its final value when its source dies reports history as if it were the present, and users read it as a live state. Label that case stale or unknown, and choose wording that does not imply a tunnel. Then let the label change as soon as the source stops.
Check What the Device Actually Reports
A physical light or a widget should be driven by a supported observation, not by a guess about the last known good state. These Android commands show the transport and the platform's always-on configuration without installing anything.
adb shell dumpsys connectivity | grep -i -A4 vpn adb shell settings get secure always_on_vpn_app adb shell settings get secure always_on_vpn_lockdown adb shell dumpsys netstats | head -40
The always-on keys tell you whether the platform is configured to keep a tunnel up and to block traffic without it; they do not tell you that the tunnel is currently healthy. Pair that configuration reading with a fresh probe before anything is displayed as connected.
If the observation cannot continue, the display must be able to say so. A lamp wired to an automation that no longer runs is worse than no lamp, because it asserts a state nobody is measuring.
Keep Warning Separate From Enforcement
An automation that notices a disconnect fires after the event, so it cannot be the boundary that stops a packet escaping during the gap. If direct fallback must be forbidden, configure the platform's blocking policy and verify it by turning the tunnel off deliberately. The indicator reports; the policy enforces.
A warning task that disables interfaces to force compliance can also lock the device out of the reconnect it needs, producing a loop where the tunnel never returns and the warning never clears.
Decide what the display should show when the observer is unsure, then test that case by stopping the observer. If the answer is still connected, the indicator is measuring the past.