playback: save when service closes

This time, actually wait for the save to complete before stopping the
foreground state. This requires some checks to make sure that we don't
have any "randomly smashing on buttons" errors, but I'm unsure if that
will be enough.

The last case in which this becomes an issue is when the service
is killed outright. I can't do much here to make the state more sane
unless I did some playback position monitoring.
This commit is contained in:
Alexander Capehart 2024-02-17 13:37:02 -07:00
parent 80e08fd74a
commit 23d561cc44
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47

View file

@ -194,6 +194,7 @@ class PlaybackService :
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
if (!playbackManager.progression.isPlaying) {
playbackManager.playing(false)
endSession()
}
}
@ -533,6 +534,7 @@ class PlaybackService :
) {
super.onPositionDiscontinuity(oldPosition, newPosition, reason)
if (reason == Player.DISCONTINUITY_REASON_SEEK) {
// TODO: Once position also naturally drifts by some threshold, save
deferSave()
}
}
@ -638,12 +640,7 @@ class PlaybackService :
// --- OTHER FUNCTIONS ---
private fun deferSave() {
currentSaveJob?.let {
logD("Discarding prior save job")
it.cancel()
}
currentSaveJob =
saveScope.launch {
saveJob {
logD("Waiting for save buffer")
delay(SAVE_BUFFER)
yield()
@ -652,6 +649,14 @@ class PlaybackService :
}
}
private fun saveJob(block: suspend () -> Unit) {
currentSaveJob?.let {
logD("Discarding prior save job")
it.cancel()
}
currentSaveJob = saveScope.launch { block() }
}
private fun broadcastAudioEffectAction(event: String) {
logD("Broadcasting AudioEffect event: $event")
sendBroadcast(
@ -664,9 +669,20 @@ class PlaybackService :
private fun endSession() {
// This session has ended, so we need to reset this flag for when the next
// session starts.
saveJob {
logD("Committing saved state")
persistenceRepository.saveState(playbackManager.toSavedState())
withContext(Dispatchers.Main) {
// User could feasibly start playing again if they were fast enough, so
// we need to avoid stopping the foreground state if that's the case.
if (!player.isPlaying) {
hasPlayed = false
playbackManager.playing(false)
foregroundManager.tryStopForeground()
}
}
}
}
/**
* A [BroadcastReceiver] for receiving playback-specific [Intent]s from the system that require