app: an IMS network is not a blocked measurement

rmnet_data1 on the OnePlus is the carrier's IMS/VoLTE network: it carries
IMS&MMTEL but neither INTERNET nor NOT_RESTRICTED, so binding needs
CONNECTIVITY_USE_RESTRICTED_NETWORKS - signature-level, unobtainable.
EPERM there is permanent and says nothing about any network's health, but
the constraint detector counted it, so a phone with VoLTE reported
'measurement blocked' on every run and every verdict came out
INCONCLUSIVE. Capabilities now decide: networks an app may never bind are
recorded as app_usable:false in networks[] and skipped, rather than
reported as something the run failed to do.

Also retires the 'while it tears down' wording, which was a guess that
turned out to be wrong - the refusal outlasts the VPN indefinitely, so
the text now names the VPN as the usual cause without asserting a
timeline it cannot know.

App version 0.2.4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mrambossek
2026-08-02 14:11:08 +02:00
co-authored by Claude Opus 5
parent d420a71a01
commit ab6e278272
7 changed files with 54 additions and 9 deletions
@@ -19,6 +19,17 @@ data class Network(
val cellular: Cellular? = null,
val changes: List<NetworkChange> = emptyList(),
@SerialName("system_verdict") val systemVerdict: SystemVerdict? = null,
/**
* Whether an ordinary app may send on this network at all.
*
* False for the carrier's special-purpose networks — IMS/VoLTE, MMS, XCAP — which appear
* beside the real ones in Android's list and carry neither `INTERNET` nor `NOT_RESTRICTED`.
* Binding to those needs `CONNECTIVITY_USE_RESTRICTED_NETWORKS`, a privileged permission no
* normal app can hold, so the refusal is permanent and says nothing about the network's
* health. Recorded rather than hidden: a reader seeing an interface with no measurements
* against it deserves to know the OS forbade them, instead of concluding the link is dead.
*/
@SerialName("app_usable") val appUsable: Boolean? = null,
)
/**