diff --git a/app/src/main/assets/pulseaudio.tzst b/app/src/main/assets/pulseaudio.tzst index 60066f1a5..3d52e1141 100644 Binary files a/app/src/main/assets/pulseaudio.tzst and b/app/src/main/assets/pulseaudio.tzst differ diff --git a/app/src/main/java/com/steamdeck/launcher/MainActivity.kt b/app/src/main/java/com/steamdeck/launcher/MainActivity.kt index ed1f1188d..b02e367b8 100644 --- a/app/src/main/java/com/steamdeck/launcher/MainActivity.kt +++ b/app/src/main/java/com/steamdeck/launcher/MainActivity.kt @@ -298,9 +298,18 @@ class MainActivity : ComponentActivity() { // The session's logs land in Downloads so a failed run can be handed over as a folder // rather than dug out of app-private storage. targetSdk 28 means the old permission still // grants exactly that. + val wanted = ArrayList() if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1) + wanted.add(Manifest.permission.WRITE_EXTERNAL_STORAGE) } + // The microphone is on by default; ask once, with the storage prompt, so voice chat works + // without a trip to the settings. A refusal is not asked again - the toggle asks when used. + if (SessionPrefs.micEnabled(this) && !SessionPrefs.micAsked(this) + && checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + wanted.add(Manifest.permission.RECORD_AUDIO) + SessionPrefs.setMicAsked(this) + } + if (wanted.isNotEmpty()) requestPermissions(wanted.toTypedArray(), 1) // A session folder left without its ending - the process was killed - gets it now. if (!SessionState.running) Thread({ SessionArtifacts.finishAbandoned(this) }, "finish-abandoned").start() } diff --git a/app/src/main/java/com/steamdeck/launcher/audio/PulseAudioComponent.java b/app/src/main/java/com/steamdeck/launcher/audio/PulseAudioComponent.java index acbaee62c..cb18481d2 100644 --- a/app/src/main/java/com/steamdeck/launcher/audio/PulseAudioComponent.java +++ b/app/src/main/java/com/steamdeck/launcher/audio/PulseAudioComponent.java @@ -28,7 +28,7 @@ public class PulseAudioComponent extends SessionPart { /** Where the guest reaches the daemon; the session exports PULSE_SERVER=unix:. */ public static final String SOCKET_NAME = "PS0"; /** Identifies the bundled pulseaudio.tzst; a change here re-unpacks it over what a device has. */ - private static final String BUNDLE_STAMP = "2026-09-23-pa13-suspend-r4"; + private static final String BUNDLE_STAMP = "2026-09-23-pa13-suspend-r5"; private final File workingDir; /** Where the daemon's own output is kept for this session, or null for logcat only. */ diff --git a/app/src/main/java/com/steamdeck/launcher/session/SessionPrefs.kt b/app/src/main/java/com/steamdeck/launcher/session/SessionPrefs.kt index 1dec83576..e2562ae89 100644 --- a/app/src/main/java/com/steamdeck/launcher/session/SessionPrefs.kt +++ b/app/src/main/java/com/steamdeck/launcher/session/SessionPrefs.kt @@ -78,8 +78,15 @@ object SessionPrefs { prefs(context).edit().putBoolean("directAudio", on).apply() } - /** The microphone, its own opt-in: the helper opens an input stream only when asked. */ - fun micEnabled(context: Context): Boolean = prefs(context).getBoolean("mic", false) + /** The microphone for voice chat, on unless turned off; used only once RECORD_AUDIO is granted. */ + fun micEnabled(context: Context): Boolean = prefs(context).getBoolean("mic", true) + + /** Whether the app has already asked for the microphone once at start-up. */ + fun micAsked(context: Context): Boolean = prefs(context).getBoolean("micAsked", false) + + fun setMicAsked(context: Context) { + prefs(context).edit().putBoolean("micAsked", true).apply() + } fun setMicEnabled(context: Context, on: Boolean) { prefs(context).edit().putBoolean("mic", on).apply()