mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-13 03:51:10 +00:00
fix: close stale Quest XR sessions before reentry
This commit is contained in:
1 parent
65c6ca3552
commit
19a8beea52
2 files changed
+62
-5
No files matched your search
@@ -2,9 +2,12 @@ package com.droiddeck.launcher
|
||||
|
||||
import android.app.NativeActivity
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import com.droiddeck.launcher.gpu.SteamVr
|
||||
import com.droiddeck.launcher.session.SessionService
|
||||
import com.droiddeck.launcher.session.SessionState
|
||||
import com.droiddeck.launcher.wayland.CompositorHost
|
||||
import com.droiddeck.launcher.wayland.WaylandCompositor
|
||||
|
||||
@@ -12,7 +15,9 @@ class QuestXrActivity : NativeActivity() {
|
||||
private var steamVrStarted = false
|
||||
@Volatile private var closing = false
|
||||
@Volatile private var steamVrStatus = SteamVr.Status.UNAVAILABLE
|
||||
private var sessionId: String? = null
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
sessionId = SessionState.sessionId
|
||||
SessionService.setXrActivityVisible(this, true)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
@@ -36,16 +41,59 @@ class QuestXrActivity : NativeActivity() {
|
||||
if (!steamVrStarted) {
|
||||
steamVrStarted = true
|
||||
Thread({
|
||||
if (!SteamVr.run(this, "start")) Log.e("DroidDeckXR", "SteamVR start failed")
|
||||
while (!closing) {
|
||||
steamVrStatus = SteamVr.status(this)
|
||||
Thread.sleep(1000)
|
||||
try {
|
||||
val started = synchronized(steamVrLock) {
|
||||
if (closing || !sessionAlive()) false else {
|
||||
steamVrOwner = this
|
||||
SteamVr.run(this, "start")
|
||||
}
|
||||
}
|
||||
if (!started) {
|
||||
leaveXr("SteamVR start failed", true)
|
||||
return@Thread
|
||||
}
|
||||
val startupDeadline = SystemClock.elapsedRealtime() + 30_000
|
||||
var lastRunning: Long? = null
|
||||
while (!closing) {
|
||||
if (!sessionAlive()) {
|
||||
leaveXr("Steam session ended", false)
|
||||
break
|
||||
}
|
||||
steamVrStatus = SteamVr.status(this)
|
||||
val now = SystemClock.elapsedRealtime()
|
||||
if (steamVrStatus == SteamVr.Status.RUNNING) lastRunning = now
|
||||
val deadline = lastRunning?.plus(5_000) ?: startupDeadline
|
||||
if (steamVrStatus != SteamVr.Status.RUNNING && now >= deadline) {
|
||||
leaveXr("SteamVR stopped or did not finish starting", true)
|
||||
break
|
||||
}
|
||||
Thread.sleep(1000)
|
||||
}
|
||||
} finally {
|
||||
synchronized(steamVrLock) {
|
||||
// A retiring activity must not stop a replacement's SteamVR session.
|
||||
if (steamVrOwner === this) {
|
||||
if (sessionAlive()) SteamVr.run(this, "stop")
|
||||
steamVrOwner = null
|
||||
}
|
||||
}
|
||||
}
|
||||
SteamVr.run(this, "stop")
|
||||
}, "quest-steamvr-start").start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun sessionAlive() = SessionState.running && !SessionState.stopRequested &&
|
||||
sessionId != null && SessionState.sessionId == sessionId
|
||||
|
||||
private fun leaveXr(reason: String, failed: Boolean) {
|
||||
Log.w("DroidDeckXR", reason)
|
||||
closing = true
|
||||
runOnUiThread {
|
||||
if (failed) Toast.makeText(this, R.string.cardboard_steamvr_failed, Toast.LENGTH_LONG).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
fun onXrFrame(frameTimeNanos: Long) {
|
||||
WaylandCompositor.nativeVsync(frameTimeNanos)
|
||||
}
|
||||
@@ -62,4 +110,9 @@ class QuestXrActivity : NativeActivity() {
|
||||
SessionService.setXrActivityVisible(this, false)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val steamVrLock = Any()
|
||||
private var steamVrOwner: QuestXrActivity? = null
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,10 @@ The panel compositor detaches before OpenXR starts displaying guest frames.
|
||||
Session suspension accounts for the immersive activity while the panel is hidden.
|
||||
Closing the immersive activity stops SteamVR. The panel remains available for
|
||||
returning to the normal Steam session.
|
||||
The immersive activity belongs to the Steam session that opened it. Ending that
|
||||
session closes XR; a failed startup or stopped SteamVR also returns to the panel
|
||||
with an error instead of leaving a black scene. Enter SteamVR can then start a
|
||||
fresh connection.
|
||||
|
||||
With Steam already running, `python3 tools/test_quest_xr.py --serial SERIAL`
|
||||
launches the immersive activity and verifies advancing owned images, tracked
|
||||
|
||||
Reference in new issue
Block a user