-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Summary
TWA packaged with horizonOSAppMode: 'immersive' launches WebXRCustomTabActivity in the VR compositor, but the web content never renders. The Horizon OS interstitial (pulsating dots) persists indefinitely, followed by "App name unavailable" error. The same TWA works correctly with horizonOSAppMode: '2D'.
Environment
| Field | Value |
|---|---|
| Headset | Meta Quest 2 |
| Firmware | Android 14 (SDK 34), Build UP1A.231005.007.A1 |
| Quest Browser | 144.2.0.29.52.912191064 |
| Bubblewrap | Meta fork v1.22.3 (latest main) |
| androidbrowserhelper | 2.5.0 |
| horizonplatformsdk | 1.1.0 |
| Host OS | Linux (Ubuntu, x86_64) |
| JDK | OpenJDK 17.0.18 |
Configuration
twa-manifest.json (relevant fields):
{
"packageId": "in.walkinto.xr",
"host": "walkinto.in",
"startUrl": "/viewer/xr/vr",
"horizonOSAppMode": "immersive",
"isMetaQuest": true,
"minSdkVersion": 23
}AndroidManifest.xml includes:
<category android:name="com.oculus.intent.category.VR" /><meta-data android:name="horizonos.pwa.APP_MODE" android:value="immersive" /><meta-data android:name="com.meta.horizon.platform.ovr.OCULUS_APP_ID" android:value="\ 26873319878939517" /><uses-permission android:name="android.permission.INTERNET" />- Digital Asset Links verified (
assetlinks.jsonlive, fingerprints match)
Reproduction Steps
bubblewrap buildwithhorizonOSAppMode: 'immersive'adb install app-release-signed.apk(or upload to RC channel viaovr-platform-util)- Launch app from Quest Library → Unknown Sources (sideload) or from Store (RC channel)
Observed Behaviour
LauncherActivitystarts → Horizon OS recognises it as immersive:VolumetricContentMonitor: Switching to immersive app. taskId: 3CustomTabsServicebinding fails (expected on Quest):W ActivityManager: Unable to start service Intent { act=android.support.customtabs.action.CustomTabsService pkg=com.oculus.browser } U=0: not found- After ~12s delay,
WebXRCustomTabActivitystarts:I ActivityTaskManager: START u0 {act=android.intent.action.VIEW dat=https://walkinto.in/viewer/xr/vr pkg=com.oculus.browser cmp=com.oculus.browser/.WebXRCustomTabActivity} - Activity gains focus then immediately loses it and stops:
cr_XRActivity: onResume! ... windowHasFocus? false cr_XRActivity: onWindowFocusChanged! ... true cr_XRActivity: onWindowFocusChanged! ... false ← instant loss cr_XRActivity: onPause! ... cr_XRActivity: onStop! ... - SurfaceSyncGroup times out after 2 seconds:
E SurfaceSyncGroup: Failed to receive transaction ready in 2000ms. Marking SurfaceSyncGroup(wmsSync-VRI[WebXRCustomTabActivity]#26) as ready E SurfaceSyncGroup: Failed to receive transaction ready in 2000ms. Marking SurfaceSyncGroup(VRI[WebXRCustomTabActivity]#27) as ready E SurfaceSyncGroup: Failed to receive transaction ready in 2000ms. Marking SurfaceSyncGroup(SurfaceView[com.oculus.browser/com.oculus.browser.WebXRCustomTabActivity]#25) as ready - User sees Horizon loading dots indefinitely, then "App name unavailable" toast.
Key Finding: Page IS Loaded
Despite the blank screen, Chrome DevTools (chrome://inspect) shows the page is fully loaded and rendered:
$ curl -s http://localhost:9222/json
[{ "title": "WalkInto XR", "url": "https://walkinto.in/viewer/xr/vr", "type": "page" }]
Evaluating JS on the page returns full DOM with all content (lobby UI, tours, navigation). The page renders correctly — the issue is that the VR compositor surface never connects to display it.
2D Mode Works
Switching to horizonOSAppMode: '2D' with com.oculus.intent.category.2D — the exact same URL loads and renders correctly as a flat panel in Horizon OS. This confirms the web content, Digital Asset Links, INTERNET permission, and TWA binding all work. Only the immersive surface pipeline fails.
Tested Both Sideload and Store (RC Channel)
- Sideloaded via
adb install: same SurfaceSyncGroup timeout - Uploaded to RC channel via
ovr-platform-util upload-quest-build: same SurfaceSyncGroup timeout - Real
OCULUS_APP_IDset in manifest: same result
Questions
- Is immersive TWA mode (
horizonOSAppMode: 'immersive') currently functional on Quest Browser v144? - Are there additional prerequisites beyond what bubblewrap generates (e.g., Horizon Store approval, specific browser flags, developer mode settings)?
- Is the
WebXRCustomTabActivitysurface pipeline expected to work for sideloaded/RC-channel apps, or only for production store-distributed apps? - The
ovr-platform-util create-pwacommand requires apwa-template.apk— is there a current version of this template available? The one in the pwabuilder-oculus repo (June 2022) is incompatible with current apktool versions.
Workaround
Using horizonOSAppMode: '2D' as a working baseline. Users can still enter WebXR immersive sessions from within the 2D panel via navigator.xr.requestSession('immersive-vr').