@@ -85,6 +85,7 @@ public partial class OsuGameAndroid : OsuGame
8585 private readonly Bindable < bool > cleanupStaleRealmFifos = new Bindable < bool > ( ) ;
8686 private readonly Bindable < bool > deferStartupNativeInit = new Bindable < bool > ( ) ;
8787 private readonly Bindable < bool > startupFrameSyncMigrationEnabled = new Bindable < bool > ( ) ;
88+ private readonly Bindable < bool > verboseLogging = new Bindable < bool > ( ) ;
8889
8990 [ Cached ( typeof ( IHighPerformanceSessionManager ) ) ]
9091 private readonly IHighPerformanceSessionManager highPerformanceSessionManager = new AndroidHighPerformanceSessionManager ( ) ;
@@ -208,16 +209,19 @@ private void load(FrameworkConfigManager frameworkConfig)
208209 LocalConfig . BindWith ( OsuSetting . AndroidCleanupStaleRealmFifos , cleanupStaleRealmFifos ) ;
209210 LocalConfig . BindWith ( OsuSetting . AndroidDeferStartupNativeInit , deferStartupNativeInit ) ;
210211 LocalConfig . BindWith ( OsuSetting . AndroidStartupFrameSyncMigrationEnabled , startupFrameSyncMigrationEnabled ) ;
212+ LocalConfig . BindWith ( OsuSetting . AndroidVerboseLogging , verboseLogging ) ;
211213
212214 // sentinelOnDisable=true → presence ⇒ "feature disabled". The
213215 // safety nets default to ON, so the sentinel is created only
214216 // when the user explicitly disables them.
215217 mirrorStartupFlag ( cleanupStaleRealmFifos , AndroidStartupFlags . FLAG_CLEANUP_REALM_FIFOS_DISABLED , sentinelOnDisable : true ) ;
216218 mirrorStartupFlag ( deferStartupNativeInit , AndroidStartupFlags . FLAG_DEFER_NATIVE_INIT_DISABLED , sentinelOnDisable : true ) ;
217219 // sentinelOnDisable=false → presence ⇒ "feature enabled". The
218- // FrameSync migration defaults to OFF, so the sentinel is
219- // created only when the user explicitly opts in.
220+ // FrameSync migration and verbose-logging toggles both default
221+ // to OFF, so the sentinel is created only when the user
222+ // explicitly opts in.
220223 mirrorStartupFlag ( startupFrameSyncMigrationEnabled , AndroidStartupFlags . FLAG_FRAME_SYNC_MIGRATION_ENABLED , sentinelOnDisable : false ) ;
224+ mirrorStartupFlag ( verboseLogging , AndroidStartupFlags . FLAG_VERBOSE_LOGGING_ENABLED , sentinelOnDisable : false ) ;
221225 }
222226 catch ( Exception e )
223227 {
@@ -1211,17 +1215,21 @@ private void handleLowLatencyAudioChanged(ValueChangedEvent<bool> e)
12111215 {
12121216 double suggested = Math . Clamp ( - latency , audioOffset . MinValue , audioOffset . MaxValue ) ;
12131217 audioOffset . Value = suggested ;
1214- Debug . WriteLine ( $ "[osu!] Audio offset auto-suggested: { suggested : F1} ms (hardware latency={ latency : F1} ms)") ;
1218+ Logger . Log ( $ "[osu!] Audio offset auto-suggested: { suggested : F1} ms (hardware latency={ latency : F1} ms)") ;
12151219 } , audioRedirector != null ? audioRedirector . Provider : IntPtr . Zero , sampleRate =>
12161220 {
12171221 audioRedirector ? . RefreshMixers ( sampleRate ) ;
1218- Debug . WriteLine ( "[osu!] Audio redirector refreshed with hardware sample rate: " + sampleRate ) ;
1222+ Logger . Log ( "[osu!] Audio redirector refreshed with hardware sample rate: " + sampleRate ) ;
12191223 } ) ;
12201224 }
12211225 catch ( Exception ex )
12221226 {
1223- Debug . WriteLine ( $ "[osu!] Failed to start Oboe bridge: { ex . Message } ") ;
1224- lowLatencyAudio . Value = false ;
1227+ // Surface to runtime.log so a user-shared log makes Oboe failures
1228+ // diagnosable. Do NOT silently flip lowLatencyAudio.Value back to
1229+ // false here — persisting that flip turns a single transient init
1230+ // failure into a permanent "Oboe doesn't work" for the user, with
1231+ // no indication that the toggle was overridden behind their back.
1232+ Logger . Log ( $ "[osu!] Failed to start Oboe bridge: { ex . Message } ", level : LogLevel . Error ) ;
12251233 }
12261234 }
12271235 else
0 commit comments