Network Test and Session Quality#
CloudXR Framework provides two quality tools for Apple native clients:
Config.networkTestruns a short pre-session network test at the start of a connection.Session.sessionQualityandSession.liveNetworkStatsmonitor quality during an active streaming session.
Use the network test when your app needs an early pass, warning, or diagnostic report before continuing with a stream. Use the session quality monitor when your app needs live status in the UI, adaptive behavior, or diagnostic logging after streaming begins. For HUD charts and raw time-series metrics, refer to HUD and Streaming Metrics.
Pre-Session Network Test#
Configure the network test before you connect. The test starts after
CloudXRSession.connect() connects to the server and the server is ready.
CloudXR Framework waits for renderable frames, collects samples for the
configured duration, and then publishes a NetworkTestReport through
Session.networkTestState.
import CloudXRKit
var config = CloudXRKit.Config()
config.networkTest = .enabled(duration: 5)
let cxrSession = CloudXRSession(config: config)
try await cxrSession.connect()
The NetworkTest modes control what happens after the test completes:
Mode |
Behavior |
|---|---|
|
Does not run the pre-session network test. |
|
Runs the test as a gate. If |
|
Runs the test and leaves the session connected even if |
|
Runs the test and disconnects when the report is complete, regardless of the result. Use this mode for diagnostics and automated checks. |
Use a duration long enough to collect representative startup samples. The CloudXR Developer Client exposes 5-second and 10-second options.
Reading Test State#
Read Session.networkTestState to show progress and retrieve the report:
import QuartzCore
switch cxrSession.networkTestState {
case .notStarted:
break
case .waitingForApp(let testDuration):
print("Waiting for renderable frames:", testDuration, "seconds")
case .running(let endTime):
let secondsRemaining = max(0, endTime - CACurrentMediaTime())
print("Network test running:", Int(secondsRemaining), "seconds remaining")
case .stopped(let report):
if let report {
print(report.description)
} else {
print("Network test stopped before a report was available")
}
}
If a session disconnects before the test completes, the state can become
.stopped(report: nil). Treat a missing report as an incomplete test rather
than a failed network result.
Understanding the Report#
NetworkTestReport includes a pass flag, four scored dimensions, packet
loss, round-trip delay, server frame rate, and a diagnostic message.
NetworkScore values are ordered from noData to excellent.
networkIsUsable is true only when the latency, jitter, bandwidth, and
device-performance scores are all poor or better.
Field |
Meaning |
|---|---|
|
Indicates whether all required scores meet the minimum usable threshold. |
|
Scores end-to-end pose-to-frame latency. |
|
Scores end-to-end pose-to-frame latency jitter. |
|
Scores stable available network bandwidth during the test. |
|
Scores client tick consistency. A low score can indicate client device load or scheduling issues. |
|
Reports the latest lost video-packet count when the stream statistics provide it. |
|
Reports a conservative round-trip delay value in milliseconds when the stream statistics provide it. |
|
Reports the average server frame rate and a low-percentile frame-rate value. |
|
Provides a short pass or failure summary. |
The latency and jitter scores are end-to-end measurements. They can be affected by network conditions, server performance, and server application frame production consistency.
In-Session Quality Monitor#
During an active stream, CloudXR Framework updates Session.sessionQuality
and Session.liveNetworkStats approximately every 5 seconds. Session is
observable, so SwiftUI views can bind to these properties directly.
import CloudXRKit
import SwiftUI
struct QualityView: View {
@Environment(CloudXRSession.self) private var cxrSession
var body: some View {
VStack(alignment: .leading) {
Text("Quality: " + cxrSession.sessionQuality.description)
if let latency = cxrSession.liveNetworkStats.latencyMilliseconds {
Text("E2E latency: " + String(latency) + " msec")
}
if let bandwidth = cxrSession.liveNetworkStats.bandwidthMbps {
Text("Available bandwidth: " + String(bandwidth) + " Mbps")
}
}
}
}
Prefer the observable sessionQuality and liveNetworkStats properties
for new apps. setNetworkQualityListener(listener:) remains available for
older integrations, but it is deprecated.
Session Quality States#
Session.SessionQuality is ordered from lowest to highest quality:
State |
Meaning |
|---|---|
|
CloudXR Framework has not collected enough live samples to report quality. |
|
The stream is unlikely to remain usable. This can occur when latency exceeds 200 msec, jitter exceeds 150 msec, or bandwidth is below 50 Mbps. |
|
The stream is usable but visibly impaired. This can occur when latency exceeds 120 msec, jitter exceeds 60 msec, or bandwidth is below 75 Mbps. |
|
The stream has acceptable quality. |
|
The stream has the best reported quality. This requires latency of 50 msec or less, jitter of 15 msec or less, and bandwidth of at least 150 Mbps. |
.noData is expected at the start of a session. The live quality window must
collect enough end-to-end latency samples before it can report a quality state.
Live Network Stats#
Session.liveNetworkStats provides the current values behind the quality
monitor:
Field |
Meaning |
|---|---|
|
End-to-end pose-to-frame latency in milliseconds. |
|
End-to-end pose-to-frame latency jitter in milliseconds. |
|
Stable available bandwidth in Mbps. |
|
Lost video-packet count reported for the current streaming stats window. |
|
Estimated network round-trip delay between the server and client in milliseconds. |
Packet loss and round-trip delay are diagnostic values. The current
sessionQuality state is computed from end-to-end latency, jitter, and
bandwidth.
Interpreting Results#
Use the pre-session network test to decide whether to continue, warn, or stop
early. Use the in-session quality monitor to react to changes while streaming.
For example, you can show a compact quality indicator, log transitions to
.degraded or .unsustainable, or adjust app-specific behavior when live
stats indicate sustained pressure.
If quality is poor, compare the scored fields before assuming the network is the only cause. Low bandwidth, packet loss, or high round-trip delay usually points to the network path. High end-to-end latency or jitter can also point to server load, server application frame pacing, or client device performance. For network requirements and topology guidance, refer to Network Setup.