Move workers to foreground service context a bit more safely (#10202)

The system will crash the app if the worker that calls setForeground() finished
before the service runner be able to call Service.startForeground(). This edge
case is not handled by WorkManager and there is no way to check if the required
calls are done.

So here we suspend the worker by an arbitrary duration assuming the transition
to foreground service is done by then.
This commit is contained in:
Ivan Iskandar
2023-12-02 23:46:59 +07:00
committed by GitHub
parent dfa5c229b3
commit 24e1b4034e
7 changed files with 41 additions and 41 deletions

View File

@@ -1,8 +1,12 @@
package eu.kanade.tachiyomi.util.system
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkInfo
import androidx.work.WorkManager
import kotlinx.coroutines.delay
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
val Context.workManager: WorkManager
get() = WorkManager.getInstance(this)
@@ -11,3 +15,21 @@ fun WorkManager.isRunning(tag: String): Boolean {
val list = this.getWorkInfosByTag(tag).get()
return list.any { it.state == WorkInfo.State.RUNNING }
}
/**
* Makes this worker run in the context of a foreground service.
*
* Note that this function is a no-op if the process is subject to foreground
* service restrictions.
*
* Moving to foreground service context requires the worker to run a bit longer,
* allowing Service.startForeground() to be called and avoiding system crash.
*/
suspend fun CoroutineWorker.setForegroundSafely() {
try {
setForeground(getForegroundInfo())
delay(500)
} catch (e: IllegalStateException) {
logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" }
}
}