diff --git a/docs/source/references/oob_teleop_control.rst b/docs/source/references/oob_teleop_control.rst index 12b01d54c2..3c1635731d 100644 --- a/docs/source/references/oob_teleop_control.rst +++ b/docs/source/references/oob_teleop_control.rst @@ -609,6 +609,21 @@ Environment variables - Non-negative delay between browser-local attempts in milliseconds (default ``3000``). The host derives its bounded recovery grace from this value and the maximum-attempt count. + * - ``TELEOP_CLIENT_STREAM_ATTACH_TIMEOUT_MS`` + - Base timeout in milliseconds for the web client to detect a stream that + never attaches (client default ``120000``; doubles per retry). ``0`` + disables this detection. Included in the generated headset URL. + * - ``TELEOP_CLIENT_WARMUP_BEGIN_TIMEOUT_MS`` + - Timeout in milliseconds for the web client to see the first decoder + warm-up signal after the stream attaches (client default ``10000``). + ``0`` disables this detection. Included in the generated headset URL. + * - ``TELEOP_CLIENT_WARMUP_END_TIMEOUT_MS`` + - Timeout in milliseconds for decoder warm-up to finish once it has begun + (client default ``30000``). ``0`` disables all warm-up detection, + including the begin timeout. Set this to ``0`` when the OpenXR + application starts after the headset connects: until it submits frames + the server sends only idle frames, which the client cannot tell apart + from a stuck warm-up. Included in the generated headset URL. * - ``USB_BACKEND_PORT`` - CloudXR backend port the headset reaches via ``adb reverse`` in ``--usb-local`` mode (default ``49100``). diff --git a/tests/python/core/cloudxr/test_oob_teleop_env.py b/tests/python/core/cloudxr/test_oob_teleop_env.py index 729f91f233..24abdb342c 100644 --- a/tests/python/core/cloudxr/test_oob_teleop_env.py +++ b/tests/python/core/cloudxr/test_oob_teleop_env.py @@ -405,6 +405,20 @@ def test_client_ui_fields_from_env_invalid_timeout_ignored( assert "streamAttachTimeoutMs" not in fields +def test_zero_warmup_timeout_env_reaches_bookmark_url( + clear_teleop_env: None, monkeypatch: pytest.MonkeyPatch +) -> None: + """0 means "disabled" to the web client, so it must survive as a field and a query param.""" + monkeypatch.setenv("TELEOP_CLIENT_WARMUP_END_TIMEOUT_MS", "0") + fields = client_ui_fields_from_env() + assert fields["warmupEndTimeoutMs"] == 0 + u = build_headset_bookmark_url( + web_client_base="https://h.test/", + stream_config={"serverIP": "10.0.0.1", "port": 48322, **fields}, + ) + assert parse_qs(urlparse(u).query)["warmupEndTimeoutMs"] == ["0"] + + def test_build_headset_bookmark_url_reconnect_enabled() -> None: """reconnectEnabled=True from stream_config is serialised as "true" in the bookmark URL.""" u = build_headset_bookmark_url(