* Add VITURE glasses support: hardware control, 3D, head tracking Glasses get their own controller over the MCU (permission, 120 Hz default, brightness, volume, sunblock, 2D/3D) and the game moves onto them when plugged in. The IMU drives Cardboard head tracking and the SteamVR driver. 3D falls back to one eye's view on phones that can't send the 3840x1080 signal. Options open from a glasses button in game and on the Steam page. * Drop the glasses settings like Steam's: Play-style button, Settings lip, tabs * Hang the glasses Settings lip over the top of the button * Space glasses MCU commands so the IMU rate sticks, fit fixed resolutions to the glasses * Keep Steam alive with SteamVR registered, run SteamVR at the glasses' rate, keep the glasses lip on top * Fit VR games on the glasses: full view, seated origin at the head, pad hands reach with the d-pad * Let the pad hands reach a metre out so buttons with deep colliders press * Show every VR frame in order at 120 fps: wait for SteamVR's GPU work, present only finished copies, skip the grace on idle shared counters * Glasses: SteamVR starts and stops with them, closer view with a field of view setting, Recenter on the pad * Glasses: SteamVR field of view defaults to 90° * VR pad hands: sticks move and aim the hands, left stick click switches the sticks to the game, d-pad pulls a held hand * Glasses: Play SteamVR beside the glasses button instead of starting SteamVR with them, pad hands drawn as Index controllers and off while other VR controllers are connected, glasses sheet tabs sized like Steam's * Track glasses mode, refresh-aware glasses window, align Play SteamVR with Play Steam * Fix 3D on the glasses: full-res SteamVR presenter, revert VR 3D at session end, coalesce vsync ticks, no session restart after end * Address review: glasses output after installs and session end, VR revert retry, display fallback, presenter swapchain retry, agent hex checks, drawer bumpers, glasses translations, docs * Harden VITURE stereo negotiation and output refresh tracking * Localize stereo recovery feedback and record Astra reconnect tests * Improve test failure diagnostics and refresh Astra firmware findings * Handle VITURE docks separately and reject truncated USB frames * Glasses: remember a 3D fallback per model, docks as display only, VR timing fixes - A 3D attempt that ends at the 640x480 fallback is remembered for that glasses model, so Play SteamVR no longer blacks out the glasses after every restart; Retry clears it and "3D for VR games" stays reachable - A VITURE Mobile Dock on its own no longer counts as glasses; through a dock Play SteamVR is hidden and the sheet shows the output and why there is no control - HDR is probed on the glasses when the session starts there - Glasses frames with a mismatched checksum are marked in the status frame log - SteamVR layer and driver vblank counters stay monotonic across refresh changes; one-eye render scale applies from activation and on mono/3D switches - Compositor binds announce the refresh clients were last told; the presenter retries a failed first swapchain - Dead strings and helpers removed; docs updated * Glasses: drop USB frames with a bad checksum * Glasses: count frames dropped for a bad checksum * Feat/viture xr (#907) * Add RayNeo Air and GT support to the XR glasses pipeline * Add RayNeo Air and GT support to the XR glasses pipeline * Checkpoint glasses tracking, calibration, and SteamVR launch integration * Checkpoint glasses tracking, calibration, and SteamVR launch integration * Add XREAL 1S support and correct GT and Pro 2 tracking * Add XREAL 1S support and correct GT and Pro 2 tracking * Fix mirrored glasses tracking and recover SteamVR after device loss * Fix mirrored glasses tracking and recover SteamVR after device loss * Document confirmed XREAL 1S brightness control * Document confirmed XREAL 1S brightness control * Fix SteamVR glasses defaults and rendering controls * Fix SteamVR glasses defaults and rendering controls * chore: keep only the 3 newest session log folders (#852) * chore: add agent comment rules (#748) Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> * Fix SteamVR polling, VITURE checksums, and fence tracking Keep manual SteamVR launches polled, discard corrupt VITURE packets, and retire Vulkan fences out of order without blocking submissions at a fixed capacity. Preserve the contiguous completion watermark used by the presenter. Fix optional Windows launcher configuration and audited helper staging. Add Android, Windows, and native tracker regression coverage. * Fix SteamVR polling, VITURE checksums, and fence tracking Keep manual SteamVR launches polled, discard corrupt VITURE packets, and retire Vulkan fences out of order without blocking submissions at a fixed capacity. Preserve the contiguous completion watermark used by the presenter. Fix optional Windows launcher configuration and audited helper staging. Add Android, Windows, and native tracker regression coverage. * fix: wireless ADB page names the child-process switch the way Android shows it (#848) * l10n: refresh stale and untranslated strings in es, fr, ko, ru (#850) * l10n: refresh stale and untranslated strings in es, fr, ko, ru - mode_added_art_hint: now mentions Steam then SteamGridDB (all four locales). - wincomp_needs_installer / wincomp_installers_note: es and ko still described the old "coming soon" behaviour; align with the current English text. - summary_remove_game: was still English in all four locales. Machine-assisted translation; native-speaker review is welcome. * l10n(es): say registro, not grabación, for the missing installer record --------- Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com> * fix: a failed cloud save recovery no longer ends the app (#846) The cloud-recovery thread started at every app start had nothing to catch an error, so one went to CrashHandler, which halts the process with status 2. In unit tests the thread can outlive the test that started it, fail on the torn-down preferences, and take the whole test run down. The error is now logged and the thread ends. Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com> * fix: an interrupted Linux runtime download resumes instead of starting again (#847) * fix: an interrupted Linux runtime download resumes instead of starting again installOnce() asked the downloader to resume but always deleted the archive in its finally block, so the next attempt began at zero. The archive is now named after the release version and checksum, a failed download keeps what it fetched, and archives of other releases (and the old fixed name) are removed. A checksum or extraction failure still deletes the file. * test: Downloader resumes a cut-off download from the bytes it kept Starts a socket server that promises the whole file, hangs up part way and then answers a Range request, and checks that the second downloadFile call resumes with the right offset and ends with identical bytes. * fix: a resumed download discards a 206 that does not start where the kept bytes end Downloader appended every 206 response to the partial file without looking at Content-Range. A server or proxy that answers a Range request with a different offset would leave a corrupt file. Check that the range starts at the kept length; otherwise delete the partial file and start again without a Range header. Adds a test with a server that answers the Range request from offset 0. --------- Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com> * l10n: German, French, Spanish, Italian, Portuguese and Russian for the zRAM, reset-settings and store free-space strings (#849) * l10n: German, French, Spanish, Italian, Portuguese and Russian for the zRAM, reset-settings and store free-space strings Adds the strings values-de, values-it and values-pt were missing (14 each) and the six that values-fr, values-es and values-ru were missing. Machine-assisted drafts that follow each file's existing register and terms; native review is welcome. * l10n: correct missing active swap translations --------- Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com> Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com> * fix: droiddeckctl reaches variant-package builds (recover #842) (#854) fix: droiddeckctl reaches builds shipped under a variant package The provider authority and the start Activity's component were fixed to com.droiddeck.launcher, so droiddeckctl could not talk to the antutu, ludashi or pubg builds from tools/release/variants.txt. DROIDDECK_PACKAGE now picks the package; the Activity's class name stays the same in every variant. Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com> * feat: droiddeckctl reports on-screen pacing (recover #843) (#855) feat: droiddeckctl pacing reports the frames that reached the screen Reads SurfaceFlinger's timestats for the game's layer (or the session's SurfaceView) over a capture: frames on screen, fps on screen, the present-to-present histogram and how many intervals were off the usual cadence. Records split by a refresh-rate change are summed. A game's own fps counter counts frames handed over, so it can't show dropped or doubled frames. Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com> * fix: Steam can restart more than twice in a session (#754) * fix: Steam can restart more than twice in a session Every exit 42 counted toward the cap that stops an update which will not install, and the count was never cleared, so the third restart of a session ended it however far apart they were. A client that ran for a minute before asking is not that loop: the count starts again. * fix: measure the client's run time as it exits The time spent collecting logs and checking FEX after the client exits counted toward its run, so a slow cleanup could make a quick exit 42 look like a long one and clear the count. --------- Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com> Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> * fix: the front end keeps its page when the Fold is folded or unfolded (#832) * fix: the front end keeps its page when the Fold is folded or unfolded MainActivity, FileManagerActivity, FilePickerActivity and StoreLoginActivity did not declare the screen-size configuration changes, so folding or unfolding a foldable recreated them and dropped their in-memory state. They now handle orientation, screenSize, screenLayout, smallestScreenSize and density themselves, like SessionActivity already does. uiMode is left out on purpose. * fix: store login keeps rebuilding its toolbar when the display density changes StoreLoginActivity builds its toolbar in code with dp-to-pixel values taken at creation time and has no onConfigurationChanged. It no longer declares density in configChanges, so a density change recreates it as before this PR. Size and layout changes are still handled in place. --------- Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com> * Release pointer buttons without replaying stale motion (#803) * Fix cursor warping on native touch down * Preserve input cleanup without replaying stale pointer motion --------- Co-authored-by: siyuan.qsy <siyuan.qsy@alibaba-inc.com> * l10n: translate the strings added since #284 into zh-CN, zh-HK, zh-TW and ja (#539) * l10n: translate the 184 strings added since #284 (zh-CN/HK/TW, ja) The stores, cloud saves, Windows components, Steam touch, desktop removal and background-downloads strings landed after #284's translation snapshot, so every one of them fell back to English. Translate all 184 into Simplified Chinese, Traditional Chinese (Taiwan and Hong Kong) and Japanese, keeping each locale file's own vocabulary (工作階段/會話, 解除安裝/卸載, 元件/組件, 設定). Also fix four Hong Kong strings that kept the simplified 着色器. * l10n(zh): fix stale and ambiguous strings found in review Severe: summary_remove_game was untranslated English in all three files; mode_added_art_hint, wincomp_installers_note and wincomp_needs_installer still described the pre-#480/#492 English. Also: distinguish the Setup wizard from Android system settings in zh-HK/zh-TW (初始設定 / 系統設定 / Android 設定), unify library as 收藏庫, component as 組件 in zh-HK, session as 會話 in zh-HK, account as 帳戶 in zh-HK, Trending as 趋势/趨勢, Forget as 清除, reword the re-applied-at-launch, action-failed and already-in-Games strings, and play as 執行/開啟遊戲 in zh-TW/zh-HK. * l10n(ja): fix stale and ambiguous strings found in review --------- Co-authored-by: Dantalian <Dantalian-dev@users.noreply.github.com> Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com> * Rebuild and verify Windows VR runtime components * Rebuild and verify Windows VR runtime components * Add top, bottom, and centered picture positions for Steam sessions (#871) * fix: dependency scan ignores folders above the game folder (#859) * DroidDeck-Proton: get releases from the Droid-Deck org repo DroidDeck-Proton is now built and released on Droid-Deck/DroidDeck-Proton (11-9.1 is Latest there), so the Components page, the update check and the guest installer read releases from the org repo instead of The412Banner's. * feat: low-latency controller and touch toggles in the session drawer (#808) * fix: SteamGridDB lookups no longer stick as "no match" after a failure; add a search to the art chooser (#876) * feat: Steam home wall fills from the signed-in library instead of store picks (#878) * test: cover GPU family and support classification (#880) * Fix local builds on Linux failing after the first Comet build (#866) * feat: sort the store library and installed tabs, and switch between card and list views (#798) * feat: three-finger tap toggles Steam's on-screen keyboard in game mode (#782) * fix: keep Quest-patched Turnip as the auto default (#853) * Fix deploy_local.sh and droiddeckctl not finding a phone connected over wireless debugging (#864) * fix: keep proot sessions alive when the kernel loses fork events (#457) * fix(quest): correct desktop and Steam display corruption across sessions (#733) fix(quest): stabilize desktop and Steam layer presentation Keep Quest SDR scenes and the black backdrop off the Android Vulkan swapchain regardless of session order or HDR preferences. Only report the first frame after client content is submitted. Add backdrop lifecycle and first-frame regression coverage. Record the user's successful Quest 3 Test 2 result. Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com> * fix: keep SteamVR syscall hooks and report Steam crashes (#905) * fix: preserve SteamVR syscall hooks * fix: report Steam crashes through gamescope * fix: honor glasses pacing and resolution in SteamVR launches --------- Co-authored-by: connor g <connorsspam1992@gmail.com> Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> Co-authored-by: Yassine Gherbi <y.gherbi.dev@gmail.com> Co-authored-by: Resul Övür <92828257+ovurrsl@users.noreply.github.com> Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com> Co-authored-by: Kirk <kirtoy.junsay@gmail.com> Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com> Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com> Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com> Co-authored-by: asdf17128 <asdf17128@gmail.com> Co-authored-by: siyuan.qsy <siyuan.qsy@alibaba-inc.com> Co-authored-by: Dantalian <wsu091227@qq.com> Co-authored-by: Dantalian <Dantalian-dev@users.noreply.github.com> Co-authored-by: The412Banner <the412banner@users.noreply.github.com> Co-authored-by: The412Banner <205237651+The412Banner@users.noreply.github.com> Co-authored-by: FX1922 <120828496+FX192@users.noreply.github.com> Co-authored-by: Muaz Kadan <32595066+muazkadan@users.noreply.github.com> Co-authored-by: kingokksa <47888451+kingokksa@users.noreply.github.com> Co-authored-by: Jamie Schenker <jam1esch3nk3r@gmail.com> Co-authored-by: Jagger15 <jagger2333@live.com> * Glasses: keep a pending 2D restore and the SteamVR recovery offer, show Play SteamVR only with a picture * Translate the glasses calibration, XREAL and SteamVR recovery strings * SteamVR recovery: give a finished teardown time to collect logs before restarting * Credit the projects the XR glasses support builds on * Joy-Cons: SteamVR hands from their gyro while SteamVR runs, one combined pad otherwise * Headsets: settings badge on Play SteamVR instead of a top-right button, both shown only once connected * Hand tracking: camera-tracked Joy-Cons and bare hands in SteamVR, drawn as white gloves - Joy-Con movement from the accelerometer (report reordering, per-Joy-Con calibration, zero-velocity updates) - MediaPipe pose and hand landmarks from the device camera, placement check, per-hand Kalman filter with the Joy-Con - No controller connected: bare camera hands with Quest-style gestures, 1€ filtered, rendered as a white glove model built from a distance field - SteamVR safe mode cleared before each start so one crash no longer blocks the driver --------- Co-authored-by: MaxsTechReview <6025299+maxjivi05@users.noreply.github.com> Co-authored-by: informalTechCode <informaltechyt@gmail.com> Co-authored-by: connor g <connorsspam1992@gmail.com> Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> Co-authored-by: Yassine Gherbi <y.gherbi.dev@gmail.com> Co-authored-by: Resul Övür <92828257+ovurrsl@users.noreply.github.com> Co-authored-by: ovurrsl <ovurrsl@users.noreply.github.com> Co-authored-by: Kirk <kirtoy.junsay@gmail.com> Co-authored-by: Kirk <12691869+KirkPatrickJunsay@users.noreply.github.com> Co-authored-by: xXJsonDeruloXx <danielhimebauch@gmail.com> Co-authored-by: angelrenefm <17342133+angelrenefm@users.noreply.github.com> Co-authored-by: asdf17128 <asdf17128@gmail.com> Co-authored-by: siyuan.qsy <siyuan.qsy@alibaba-inc.com> Co-authored-by: Dantalian <wsu091227@qq.com> Co-authored-by: Dantalian <Dantalian-dev@users.noreply.github.com> Co-authored-by: The412Banner <the412banner@users.noreply.github.com> Co-authored-by: The412Banner <205237651+The412Banner@users.noreply.github.com> Co-authored-by: FX1922 <120828496+FX192@users.noreply.github.com> Co-authored-by: Muaz Kadan <32595066+muazkadan@users.noreply.github.com> Co-authored-by: kingokksa <47888451+kingokksa@users.noreply.github.com> Co-authored-by: Jamie Schenker <jam1esch3nk3r@gmail.com> Co-authored-by: Jagger15 <jagger2333@live.com>
15 KiB
XREAL 1S / One Pro feasibility — 2026-10-14
The user owns XREAL 1S and also wants One Pro support. Supporting these in DroidDeck is feasible based on existing open drivers, but the supplied Monado Air driver is not their transport. The initial investigation below preceded implementation. An experimental native 1S driver is now enabled; see the hardware validation section at the end for what has actually been verified.
Supplied Monado source
Inspected C:/Users/conno/Downloads/monado-main/monado-main/src/xrt/drivers/xreal_air/
and src/xrt/targets/common/target_builder_xreal_air.c.
| Model | USB vendor:product | Sensor/control interface | Sensor report |
|---|---|---|---|
| Air | 3318:0424 | 3 / 4 | 64 bytes |
| Air 2 | 3318:0428 | 3 / 4 | 64 bytes |
| Air 2 Pro | 3318:0432 | 3 / 4 | 64 bytes |
| Air 2 Ultra | 3318:0426 | 2 / 0 | 512 bytes |
This driver implements HID IMU input, segmented factory-calibration JSON reads, gravity/gyro fusion, brightness 0–7 and 2D/3D mode commands. It does not register 1S or One Pro. Copying those Air HID commands to the new products is unjustified. Its source carries Tobias Frisch's BSL-1.0 notice.
Applicable One-family references
- XRLinuxDriver, inspected commit
36e2139dd482f5984112d0c3ebafcc07a78f99c0.src/devices/xreal.clists vendor3318, One Pro products0435/0436, and 1S products043d/043e. These use the non-HID transport. Its README explicitly lists both models and requires current firmware with glasses stabilization/anchor disabled when using external tracking. - xrealOneDeviceKit, inspected commit
f5833f611265f418b1ea549da20dc4764d86a4ec. Its IMU adapter consumes the One TCP driver, interprets gyro as radians/sec and acceleration as m/s², then feeds fusion. Its factory-calibration JSON hook returns unsupported. The maintained Linux integration disables its SBS-control capability when no MCU connection is open; a static model table alone is not proof of working display switching. - xreal_one_driver, MIT,
inspected commit
3e912315ec16e94e9a47688770d649cfef293624. Opens TCP169.254.2.1:52998with a two-second timeout, assembles 84-byte IMU records, reads a timestamp at byte 14, gyro floats at 34 and acceleration floats at 46. This is a transport/parser reference, not a drop-in Android glasses controller.
The source check confirms a practical path for both requested models. It does not establish that this Samsung phone exposes the glasses' USB Ethernet interface to ordinary Android apps, or establish the physical tracking axes on this hardware.
DroidDeck integration path
- Attach the 1S and inspect its USB descriptors, presentation display identity, Ethernet network/link properties and whether the IMU endpoint is reachable. Obtain the same evidence for One Pro before claiming hardware validation.
- Add exact model discovery and external-display selection. Preserve each panel's Android-advertised dimensions and modes; do not assume the Air's resolution.
- Implement a bounded One-family stream parser and cancellable socket transport.
On Android, bind the socket to the relevant Ethernet
Networkwhen available, leaving Steam's Internet route alone. If Android does not expose that link, a USB network transport is additional work; no root requirement is assumed. - Establish gyro units, timestamp deltas and axis mapping using stationary, directed yaw, pitch and roll captures. Route the validated fused pose through the same glasses/HeadTracker/SteamVR pipeline as VITURE and RayNeo. Avoid layering DroidDeck tracking on top of the glasses' own anchor/stabilization.
- Gate brightness and automatic stereo switching separately on a verified control protocol. IMU streaming alone does not justify showing those controls as working.
- Test malformed/fragmented/coalesced records, missing network, timeout/reconnect, USB detach, screen handoff, SteamVR launch and each physical movement direction.
At this initial investigation stage, no external SDK was installed, firmware was modified, or XREAL commands were sent.
Further source investigation while the phone charges
Inspected xr-tools, commit
65c11105434a998f09ac4a5f8e4de8736bb4d36c, particularly
packages/xreal_one_driver/src/proto/net/, src/proto/usb/mod.rs, and the IMU
example. This describes considerably more of the One protocol than the simple
TCP IMU reader above:
- Reports use TCP
169.254.2.1:52998; controls use169.254.2.1:52999. Both have a two-byte message identifier followed by a four-byte big-endian body length. Control messages additionally contain a big-endian transaction ID and protobuf payload. A port must bound lengths, use unique transaction IDs, enforce deadlines, and close both sockets on detach. - Sensor messages
28 36have a 128-byte body, hence 134 bytes including the header. The older reader's 84-byte extraction is not the complete frame format. Body offsets: device ID 0, device timestamp 8, report type 24, gyro 28, acceleration 40, magnetometer 52, temperature 64 and IMU ID 68. Numeric sensor fields are little-endian; timestamp is documented as nanoseconds, gyro rad/s, acceleration m/s². Type 11 is IMU; type 4 is magnetometer. Do not interpret every report as gyro data or use arrival time as the device's integration interval. - Control
27 1freads factory JSON: IMU bias, temperature-dependent gyro bias, and display-to-IMU transforms. Its example subtracts the factory biases, fuses gyro/acceleration and applies the display rotation. This is preferable to guessing a fixed mounting angle, but the example's frame convention still needs conversion and directed-motion verification in DroidDeck. 27 1csets brightness 0–9;27 27sets dimming;28 22selects regular/SBS input;27 5e/5freads/sets display configuration;28 a6/a7reads/sets EIS. Documented display configurations are 1920×1080 at 60/90/120 Hz and 3840×1080 at 60 Hz. These are evidence for One/One Pro, not confirmed 1S modes. Preserve the Android-advertised modes and verify controls separately on 1S firmware.28 29is labelled buttons-enabled/buttons-disabled scene mode. Do not assume that command disables stabilization; the separate EIS control exists.- This project's USB detection labels
3318:0436One Pro and3318:0438One as normal devices, and0435/0437as recovery devices. XRLinuxDriver accepting both IDs does not justify opening recovery products as ordinary glasses or sending firmware commands. xr-tools does not register 1S; its applicability there is a protocol-family inference, not hardware validation.
No license file or Cargo license declaration was found in this inspected xr-tools revision. No implementation was copied into DroidDeck. Use protocol observations for an independently written adapter, or resolve source licensing before a port. The MIT TCP driver and GPL XRLinuxDriver remain explicitly licensed references.
Also inspected XRLinuxDriver commit
05d0cfb.
It moves per-device pitch adjustment into the core pose path, after coordinate
conversion; it does not add an Android transport or new One control protocol.
Its pitch constants should not replace the GT mapping already verified by the user.
Next hardware check remains read-only: enumerate the 1S USB interfaces, display and Ethernet link; attempt bounded reads from both TCP services, save the factory configuration, then capture stationary/yaw/pitch/roll data. No XREAL support is advertised in this build. Android Ethernet availability and 1S control compatibility are still unverified.
Official XREAL documentation and SDK inspection
Checked the user's official documentation on 2026-10-14. This establishes an additional integration candidate alongside the direct TCP driver; it does not make that candidate a drop-in Android controller.
- The device page explicitly includes One, One Pro and 1S in the X1-based One family with rotational tracking.
- SDK 3.1.0 release notes add positional tracking for the One series with XREAL Eye and updated firmware. Beam Pro and Samsung S25 are its listed tested hosts. This does not establish 6DoF on a camera-less 1S or validation on the user's SM-F976U.
- ControlGlasses is a required server for official SDK apps on compatible Android phones. It supplies device services, 3D switching and dynamically loaded algorithm libraries. Beam Pro uses MyGlasses instead. An SDK integration would have a companion-app/version dependency.
- The quickstart describes Unity XR Plugin integration, ARM64 and OpenGL ES3. The dual-display guide confirms separate phone/glasses views and continued glasses output while the phone runs another app. This demonstrates the desired behavior in the SDK; it does not itself supply a native Kotlin implementation.
- The compatibility page currently flags unresolved Android 16 compatibility. The FAQ also says DeX can interfere with SDK display operation, and Android 16 USB permission may require camera permission first when the device exposes an enabled UVC interface. Apply that permission requirement only when relevant; ordinary tracking must not start camera capture or enable UVC automatically.
Downloaded, but did not install or bundle, the official release archive linked
from the 3.1.0 release notes:
https://public-resource.xreal.com/download/XREALSDK_Release_3.1.0.20251125/com.xreal.xr.tar.gz.
SHA-256: fd7d0fce103712e7acc85bfcbb8b127007e1d84f64596efb6c11580bea058d90.
Size: 248,169,074 bytes.
Package inspection found Android AARs including nr_api and nr_loader, ARM64
libXREALXRPlugin.so / libXREALNativeSessionManager.so, and Java
com.xreal.sdk.display.GlassesDisplay plus display/surface listeners. The C# layer
calls native exports for tracking type, resolution, refresh rate, component poses
and session lifecycle; the loader also integrates Unity subsystems. Presence of
these libraries does not establish a supported standalone JNI API or permission
to redistribute a stripped subset. No C headers were present in the archive file
listing inspected. No SDK source or binaries were added to the app.
Decision: retain both candidates. Before choosing the official native-library route, establish non-Unity initialization, head-pose access, ControlGlasses compatibility, display-surface ownership and distribution terms. Before choosing direct TCP, establish the Android network link and 1S protocol behavior. Compare both against DroidDeck's existing compositor instead of replacing its rendering architecture merely to fit the SDK's Unity sample.
Native 1S implementation and hardware validation
The pre-implementation checkpoint is 4b045519. The new driver uses independently
written Kotlin TCP framing, control transactions, sensor parsing and gyro/gravity
fusion. It does not bundle XREAL SDK binaries or copy the unlicensed xr-tools
source. Protocol observations came from the references above and
xr-tools, inspected commit
65c11105434a998f09ac4a5f8e4de8736bb4d36c.
Verified on the connected SM-F976U (Android reports release 17):
- Normal 1S USB identity is
3318:043e, product nameXREAL 1S. Only that exact product enables this driver; Air, One Pro and alternate/recovery IDs are excluded. - Android exposes NCM/ECM Ethernet networks at
169.254.2.10/24and169.254.1.10/24. Individual sockets bound to the first network reach the glasses at169.254.2.1, control port 52999 and report port 52998. The process default network remains unchanged, preserving Steam's Internet connectivity. - Requests require the high bit of the transaction ID; responses clear that bit. Replies must match both command and transaction before values are published.
- GET_DISPLAY returned payload
22 02 10 1d: mode 29, with Android reporting 1920 x 1200 at 60 Hz. This differs from the older One's mode 2 (1080 lines). The 1S default 60 Hz mapping preserves mode 29. - A two-second capture delivered 2,000 valid IMU poses (1,000 Hz). Reports use the 128-byte body, type 11, little-endian device nanoseconds and float radians/sec / m/s² format. The framing handles partial and coalesced TCP reads.
The driver plugs into the shared glasses display and head-pose paths, including SteamVR. The FOV calculation now uses the actual per-eye aspect ratio, including the 1S's 16:10 display. Controls use acknowledged commands, bounded queues and timeouts; connection failures clear tracking state and retry. Volume is hidden because no volume protocol has been established. Missing Ethernet is reported without requesting HID permission or claiming USB interfaces from Android.
Directed wearer captures on the same device established the 1S sensor basis:
level acceleration is approximately (0, -9.65, -1.07) m/s²; turning left gives
negative gyro Y; looking up gives positive gyro X; tilting toward the right
shoulder gives positive gyro Z with negative acceleration X. Both vectors are
mapped as (x, -y, -z) into the shared right/up/back basis before initial gravity
alignment and fusion. No RayNeo GT mounting angle is reused. Regression tests
exercise those measured signs through HeadPose, check an upright first pose
before recenter, and preserve the device's radians/sec and nanosecond units.
Stereo switching was verified at 3840 x 1080 / 60 Hz, returning to native
1920 x 1200. On 1S, SET_INPUT performs the EDID switch itself; immediately sending
SET_DISPLAY returns busy status 5001 (22 03 08 89 27). The driver now polls
GET_DISPLAY across the temporary empty reply (22 00) and only sends a second
mode command if the settled mode differs. Hardware retesting kept the connection
and sensor stream running through the switch. The busy status is never accepted
as a successful acknowledgement.
After installing the corrected build on 2026-10-14, the wearer confirmed that the view and motion feel good in response to the upright-view, yaw, pitch and head-tilt check. The SteamVR-requested session was running with a rendered first frame, stereo output and active tracking. All 181 glasses, shared-pose, SteamVR launch and glasses-UI regression checks passed; packaged runtime inputs verified.
The wearer also confirmed on 2026-10-14 that XREAL 1S brightness control works. Higher refresh rates were not tested.
Still experimental: dimmer, 90/120 Hz compatibility modes and extended gameplay stability need hardware validation. One successful view/motion check does not establish long-session stability. Users must select Follow mode and disable the glasses' own stabilization. Factory calibration and XREAL Eye/6DoF are not implemented. One Pro is not enabled or claimed as tested.