feat(client/android): the speed test, writing where the tested host actually reads
Android had no speed test at all — the one client where "what bitrate should I use?" had no answer but guessing. It measures over the REAL data plane: a minimal 720p connect, then the host bursts filler for two seconds, so the answer is about the link this host's stream will take rather than generic throughput. Two new JNI calls (`nativeSpeedTest` / `nativeProbeResult`) front the core's probe, deliberately measure-only. The measurement is the easy half. The half that was wrong on every client for a long time is WHERE the answer goes. A measured bitrate belongs in the layer the tested host actually resolves bitrate from (design §5.3): its bound profile's override if it has one, the global if the host is unbound — and if the host is bound to a profile that INHERITS bitrate, both are defensible, so the user gets both buttons instead of us guessing. That target depends only on the host, so it is known before the result lands and the button can say where it will write: "Apply to “Travel”". Writing the global unconditionally — the old behaviour everywhere — is what made measuring the slow box downstairs quietly re-tune the desktop. Reachable from the host card's overflow and from the console's host options: a TV box on a powerline adapter is exactly the machine whose link is worth measuring, even though profile editing stays off that surface. While there: a successful write no longer renders in the error container. The connect screen's one status line was red by design — correct for a failure, a small lie for "75 Mbit/s set in “Travel”" — so confirmations got their own. Verified on the emulator against a real host: 108 Mbit/s measured on a host bound to a bitrate-setting profile, target resolved to that profile, and Apply wrote 75397 kbps into the profile's overlay with the global untouched and the profile's other overrides unmoved.
This commit is contained in:
@@ -145,6 +145,24 @@ object NativeBridge {
|
||||
*/
|
||||
external fun nativeProbe(host: String, port: Int, timeoutMs: Int): Boolean
|
||||
|
||||
/**
|
||||
* Start a bandwidth speed test on [handle]: the host bursts filler over the real data plane at
|
||||
* [targetKbps] of goodput for [durationMs] (each clamped host-side to ≤ 3 Gbps / ≤ 5 s),
|
||||
* **briefly pausing video**. Measuring over the stream's own path is the point — the answer is
|
||||
* about the link this host's stream will take, not about generic throughput.
|
||||
*
|
||||
* Non-blocking: poll [nativeProbeResult] until it reports done. Starting a probe resets any
|
||||
* prior measurement. Returns false on a dead handle. Cheap; safe on the main thread.
|
||||
*/
|
||||
external fun nativeSpeedTest(handle: Long, targetKbps: Int, durationMs: Int): Boolean
|
||||
|
||||
/**
|
||||
* The current speed-test measurement, partial until `[0] != 0.0`:
|
||||
* `[done, throughputKbps, lossPct, hostDropPct, elapsedMs, recvBytes]`. Zeros before any
|
||||
* probe, null on a dead handle. Cheap (one lock + a copy); safe to poll on the main thread.
|
||||
*/
|
||||
external fun nativeProbeResult(handle: Long): DoubleArray?
|
||||
|
||||
/**
|
||||
* Apply the user's "Low-latency mode (experimental)" toggle to the process-wide transport
|
||||
* defaults — today just DSCP/QoS marking on the media sockets. Must be called BEFORE
|
||||
|
||||
Reference in New Issue
Block a user