diff --git a/app/src/main/java/com/droiddeck/launcher/runtime/GuestCommand.kt b/app/src/main/java/com/droiddeck/launcher/runtime/GuestCommand.kt index 1f8a7233d..3dd7ec189 100644 --- a/app/src/main/java/com/droiddeck/launcher/runtime/GuestCommand.kt +++ b/app/src/main/java/com/droiddeck/launcher/runtime/GuestCommand.kt @@ -47,7 +47,7 @@ object GuestCommand { .forEach { cmd.add("-b"); cmd.add(it) } cmd += listOf( "/usr/bin/env", "-i", "HOME=/root", "USER=root", "LANG=C.UTF-8", - "PATH=/usr/local/bin:/usr/bin:/bin", "XDG_RUNTIME_DIR=${runtimeDir.path}", + "PATH=/usr/local/bin:/usr/bin:/bin", "XDG_RUNTIME_DIR=${LinuxRuntime.GUEST_RUNTIME_DIR}", "XDG_DATA_HOME=/root/.local/share", "FLATPAK_BWRAP=${FlatpakManager.BWRAP}", "XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/usr/local/share:/usr/share", ) diff --git a/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntime.java b/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntime.java index 22feae5ce..43d068701 100644 --- a/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntime.java +++ b/app/src/main/java/com/droiddeck/launcher/runtime/LinuxRuntime.java @@ -34,6 +34,14 @@ public final class LinuxRuntime { /** Shortcut extra naming which of the modes above a Linux entry launches. */ public static final String EXTRA_LINUX_MODE = "linux_mode"; private static final String KGSL_DEVICE = "/dev/kgsl-3d0"; + /** + * Where the guest sees a command's XDG_RUNTIME_DIR. A Unix socket's path must fit in 108 bytes, + * and libwayland checks the guest's path before proot ever sees it: with the app on an SD card + * adopted as internal storage the files directory is /mnt/expand//user/0//files, + * and gamescope-0 under it is one byte over, so gamescope could not open its socket and the + * session ended at once. A long host path behind it is proot's to shorten. + */ + public static final String GUEST_RUNTIME_DIR = "/run/droiddeck"; /** Where every Linux session's debug log lands: public, so a user can just hand the folder over. */ public static final String DEBUG_LOG_DIR = "DroidDeck"; @@ -185,7 +193,10 @@ public final class LinuxRuntime { bind(cmd, new File(root, "etc/bannerlator/empty").getPath() + ":/sys/fs/selinux"); bind(cmd, context.getFilesDir().getPath()); bind(cmd, context.getCacheDir().getPath()); - if (runtimeDir != null) bind(cmd, runtimeDir.getPath()); + if (runtimeDir != null) { + bind(cmd, runtimeDir.getPath()); + bind(cmd, runtimeDir.getPath() + ":" + GUEST_RUNTIME_DIR); + } if (sessionRoot != null) bind(cmd, sessionRoot.getPath()); if (externalStorage != null && externalStorage.isDirectory()) { bind(cmd, externalStorage.getPath()); diff --git a/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt b/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt index fd51da14b..17eb197dd 100644 --- a/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt +++ b/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt @@ -277,7 +277,7 @@ class SessionService : Service() { // The desktop's Steam launchers start the client there (bannerlator-steam-launch), through the // same set-up as a Steam session: it gets what the client and its games are started with. val steamHere = SessionState.mode == MODE_STEAM || SessionState.mode == MODE_DESKTOP - addClientEnvironment(guest, runtimeDir, steamHere) + addClientEnvironment(guest, steamHere) val pulse = startAudio(guest, sessionDir) @@ -483,7 +483,7 @@ class SessionService : Service() { } /** The guest's base environment: paths, the display, the GL/Vulkan stack and the client's switches. */ - private fun addClientEnvironment(guest: MutableList, runtimeDir: File, steamHere: Boolean) { + private fun addClientEnvironment(guest: MutableList, steamHere: Boolean) { guest.add("/usr/bin/env") guest.add("-i") guest.add("HOME=/root") @@ -494,7 +494,7 @@ class SessionService : Service() { // Without this the session is UTC: the client's clock, its logs and every timestamp in a // session bundle sit hours off the device's. Bannerlator carries the same line. guest.add("TZ=" + java.util.TimeZone.getDefault().id) - guest.add("XDG_RUNTIME_DIR=" + runtimeDir.path) + guest.add("XDG_RUNTIME_DIR=" + LinuxRuntime.GUEST_RUNTIME_DIR) guest.add("XDG_SESSION_TYPE=wayland") guest.add("WAYLAND_DISPLAY=wayland-0") guest.add("GAMESCOPE_FORCE_GENERAL_QUEUE=1")