Fix ExoPlayer wrong-thread crash + recordSearch off Main (perf-audit pass-2) — vc=79
- PlaybackService: the pauseOnHeadphoneDisconnect settings-watcher collector
ran on globalScope (Dispatchers.IO) and called setHandleAudioBecomingNoisy
on the ExoPlayer, which is thread-affine to the Main thread it was built on
→ latent IllegalStateException('Player accessed on the wrong thread') that
fires every service start (the StateFlow emits on first subscription). Run
the collector on Dispatchers.Main (mirrors resumePollJob).
- SearchViewModel: recordSearch (json-encode + SharedPrefs write) was on Main;
wrap in withContext(Dispatchers.IO).
Both adversarially verified in the multi-agent perf audit (pass 2).
This commit is contained in:
parent
2defbd2925
commit
96bad228ef
3 changed files with 19 additions and 4 deletions
|
|
@ -9,6 +9,14 @@ const val STRAW_SDK_TARGET = 35
|
||||||
|
|
||||||
// Sulkta fork — Straw
|
// Sulkta fork — Straw
|
||||||
//
|
//
|
||||||
|
// vc=79 / 0.1.0-CM — perf-audit pass-2 (app-side slam-dunks):
|
||||||
|
// * FIX a wrong-thread crash: the headphone-disconnect settings watcher
|
||||||
|
// ran on the IO scope and touched the ExoPlayer (thread-affine to the
|
||||||
|
// Main thread it was built on) → "Player accessed on the wrong thread"
|
||||||
|
// latent on every session. Collector now runs on Dispatchers.Main.
|
||||||
|
// * recordSearch (json-encode + SharedPrefs write) moved off the Main
|
||||||
|
// thread into withContext(Dispatchers.IO).
|
||||||
|
//
|
||||||
// vc=78 / 0.1.0-CL — perf-audit batch 1 (app-side):
|
// vc=78 / 0.1.0-CL — perf-audit batch 1 (app-side):
|
||||||
// * Autoplay-next no longer drops the user's max-resolution cap. The
|
// * Autoplay-next no longer drops the user's max-resolution cap. The
|
||||||
// enter-video track-selection reset built params from scratch, wiping
|
// enter-video track-selection reset built params from scratch, wiping
|
||||||
|
|
@ -100,6 +108,6 @@ const val STRAW_SDK_TARGET = 35
|
||||||
// vc=19 / 0.1.0-AE — rust pipeline cutover. Extraction via
|
// vc=19 / 0.1.0-AE — rust pipeline cutover. Extraction via
|
||||||
// strawcore-core (Sulkta-Coop/strawcore) via the UniFFI wrapper; no
|
// strawcore-core (Sulkta-Coop/strawcore) via the UniFFI wrapper; no
|
||||||
// NewPipeExtractor in the runtime path.
|
// NewPipeExtractor in the runtime path.
|
||||||
const val STRAW_VERSION_CODE = 78
|
const val STRAW_VERSION_CODE = 79
|
||||||
const val STRAW_VERSION_NAME = "0.1.0-CL"
|
const val STRAW_VERSION_NAME = "0.1.0-CM"
|
||||||
const val STRAW_APPLICATION_ID = "com.sulkta.straw"
|
const val STRAW_APPLICATION_ID = "com.sulkta.straw"
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,13 @@ class PlaybackService : MediaSessionService() {
|
||||||
// without requiring a service restart. The initial value was
|
// without requiring a service restart. The initial value was
|
||||||
// baked in via the builder above — this picks up subsequent
|
// baked in via the builder above — this picks up subsequent
|
||||||
// flips.
|
// flips.
|
||||||
settingsWatcherJob = StrawApp.globalScope.launch {
|
// MUST run on Main: globalScope is Dispatchers.IO, but ExoPlayer is
|
||||||
|
// thread-affine to the Main thread it was built on (onCreate), so
|
||||||
|
// touching it (setHandleAudioBecomingNoisy) off-Main throws
|
||||||
|
// "Player is accessed on the wrong thread" — and this hot StateFlow
|
||||||
|
// emits on first subscription, i.e. every service start. Mirrors
|
||||||
|
// resumePollJob below.
|
||||||
|
settingsWatcherJob = StrawApp.globalScope.launch(Dispatchers.Main) {
|
||||||
Settings.get().pauseOnHeadphoneDisconnect.collect { handle ->
|
Settings.get().pauseOnHeadphoneDisconnect.collect { handle ->
|
||||||
player.setHandleAudioBecomingNoisy(handle)
|
player.setHandleAudioBecomingNoisy(handle)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,8 @@ class SearchViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
// Record AFTER the search succeeds so mistyped queries
|
// Record AFTER the search succeeds so mistyped queries
|
||||||
// that error out don't pollute the recent-searches list.
|
// that error out don't pollute the recent-searches list.
|
||||||
runCatching { History.get().recordSearch(q) }
|
// Off Main — recordSearch json-encodes + writes SharedPrefs.
|
||||||
|
withContext(Dispatchers.IO) { runCatching { History.get().recordSearch(q) } }
|
||||||
if (Settings.get().cacheEnabled.value) {
|
if (Settings.get().cacheEnabled.value) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
// Re-check active state after the dispatcher
|
// Re-check active state after the dispatcher
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue