Skip to content

FIX: [UUM-139700] Inherit canRunInBackground from the base layout - #2498

Open
chris-at-unity wants to merge 2 commits into
Unity-Technologies:developfrom
chris-at-unity:xr/fix-xrhmd-layout-run-in-background-after-pause
Open

chris-at-unity wants to merge 2 commits into
Unity-Technologies:developfrom
chris-at-unity:xr/fix-xrhmd-layout-run-in-background-after-pause

Conversation

@chris-at-unity

@chris-at-unity chris-at-unity commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Description

When an XR headset's OS menu is brought up, after the device went to sleep and waked up while and an XR app is running in the background, the app's environment would be locked to a floor-level view with no position nor rotation tracking. This process was not always consistent, it would take some sleep-awake cycles before the behavior showed up. This issue was reported for both Meta Quest and Android XR headsets, although the behavior was more readily reproduced on Android XR systems.

The root cause of the bug is that when an XR app is paused, the XRInputSubsystem react by stopping the XR plugins, disconnecting all associated XR devices, which includes the XRHMD device used for tracking position and rotation of the XR headset. Then, when the app is resumed, the devices are reconnected again. This in turn causes the freshly created XRHMD device to be regenerated at runtime. This input device is generated entirely from scratch by the XRLayoutBuilder.Build method using the GenericXRDevice layout as template. Then, the Input System attempts to use the previous device to pass over parameters to the new instance. However, only a subset of parameters is copied between instances, being the canRunInBackground parameter missing from the process. This causes the new XRHMD device unable to run in background, causing the loss of tracking when the app is paused due to the OS menu taking focus. This parameter is cached, so there's no way to recover the tracking through the device alone.

The proposed fixes address this cause by introducing a new mechanism that makes sure the canRunInBackground parameter is also transferred before the new device is initialized. This ensures new devices inherit the capability of running on background if the original device also supported it.

Testing status & QA

Manual testing steps:

  • Built the changes with a Unity 7.0a4, Mono editor.
  • Created a VR Template project based around the trunk release.
  • Replaced OpenXR plugin to a locally sourced version.
  • Deployed the VR template to as an APK to an Android XR device.
  • Ran the app, then let the device go to sleep, waked it up and brought out the OS menus. Made sure that the app was still tracking position and rotation on background. Repeated this cycle 3 times.

Added automated tests to verify that canRunInBackground parameter in the XR HMD device is preserved, and that XRInputSubsystem can disambiguate a disconnect-reconnect cycle for the same device.

Overall Product Risks

Please rate the potential complexity and halo effect from low to high for the reviewers. Note down potential risks to specific Editor branches if any.

  • Complexity: Low.
  • Halo Effect: Low.

Comments to reviewers

This PR is compliment to an internal backport PRs that address the same issue. See the ticket for more details and the internal PRs.

Checklist

Before review:

  • Changelog entry added.
    • Explains the change in Changed, Fixed, Added sections.
    • For API change contains an example snippet and/or migration example.
    • JIRA ticket linked, example (case %%). If it is a private issue, just add the case ID without a link.
    • Jira port for the next release set as "Resolved".
  • Tests added/changed, if applicable.
    • Functional tests Area_CanDoX, Area_CanDoX_EvenIfYIsTheCase, Area_WhenIDoX_AndYHappens_ThisIsTheResult.
    • Performance tests.
    • Integration tests.
  • Docs for new/changed API's.
    • Xmldoc cross references are set correctly.
    • Added explanation how the API works.
    • Usage code examples added.
    • The manual is updated, if needed.

During merge:

  • Commit message for squash-merge is prefixed with one of the list:
    • NEW: ___.
    • FIX: ___.
    • DOCS: ___.
    • CHANGE: ___.
    • RELEASE: 1.1.0-preview.3.

chris-at-unity and others added 2 commits October 15, 2026 11:33
MergeLayout inherited updateBeforeRender from the base layout but not
canRunInBackground. Generated XR HMD layouts therefore lost XRHMD's
canRunInBackground = true and fell back to QueryCanRunInBackground, whose
result is cached for the device's lifetime. If that query failed while the
XR provider was reconnecting devices after an app pause, the HMD was reset
on every focus loss and the view froze at the tracking origin.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chris-at-unity
chris-at-unity marked this pull request as ready for review October 16, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant