diff --git a/next/src/main/kotlin/org/fdroid/install/AppInstallManager.kt b/next/src/main/kotlin/org/fdroid/install/AppInstallManager.kt index 230ec3691..b72932520 100644 --- a/next/src/main/kotlin/org/fdroid/install/AppInstallManager.kt +++ b/next/src/main/kotlin/org/fdroid/install/AppInstallManager.kt @@ -128,6 +128,7 @@ class AppInstallManager @Inject constructor( return currentState } val iconDownloadRequest = iconModel as? DownloadRequest + currentCoroutineContext().ensureActive() val job = scope.async { startInstall( appMetadata = appMetadata, diff --git a/next/src/main/kotlin/org/fdroid/repo/RepoUpdateManager.kt b/next/src/main/kotlin/org/fdroid/repo/RepoUpdateManager.kt index 4ab01f18e..de8b5c154 100644 --- a/next/src/main/kotlin/org/fdroid/repo/RepoUpdateManager.kt +++ b/next/src/main/kotlin/org/fdroid/repo/RepoUpdateManager.kt @@ -5,6 +5,8 @@ import android.text.format.Formatter import android.util.Log import androidx.annotation.WorkerThread import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.map @@ -142,6 +144,7 @@ class RepoUpdateManager( @WorkerThread suspend fun updateRepos() { + currentCoroutineContext().ensureActive() if (isUpdating.value) { // This is a workaround for what looks like a WorkManager bug. // Sometimes it goes through scheduling/cancellation loops @@ -158,6 +161,7 @@ class RepoUpdateManager( } _isUpdating.value = true try { + currentCoroutineContext().ensureActive() var reposUpdated = false val repoErrors = mutableListOf>() // always get repos fresh from DB, because @@ -167,6 +171,7 @@ class RepoUpdateManager( // it might not be in the FDroidApp list, yet db.getRepositoryDao().getRepositories().forEach { repo -> if (!repo.enabled) return@forEach + currentCoroutineContext().ensureActive() // show notification if (isUpdateNotificationEnabled) { diff --git a/next/src/main/kotlin/org/fdroid/repo/RepoUpdateWorker.kt b/next/src/main/kotlin/org/fdroid/repo/RepoUpdateWorker.kt index e18465dbe..7ee9165be 100644 --- a/next/src/main/kotlin/org/fdroid/repo/RepoUpdateWorker.kt +++ b/next/src/main/kotlin/org/fdroid/repo/RepoUpdateWorker.kt @@ -20,6 +20,8 @@ import androidx.work.WorkerParameters import androidx.work.workDataOf import dagger.assisted.Assisted import dagger.assisted.AssistedInject +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import mu.KotlinLogging @@ -116,6 +118,7 @@ class RepoUpdateWorker @AssistedInject constructor( } val repoId = inputData.getLong("repoId", -1) return try { + currentCoroutineContext().ensureActive() if (repoId >= 0) repoUpdateManager.updateRepo(repoId) else repoUpdateManager.updateRepos() Result.success() diff --git a/next/src/main/kotlin/org/fdroid/updates/AppUpdateWorker.kt b/next/src/main/kotlin/org/fdroid/updates/AppUpdateWorker.kt index dbb371379..dd10d987b 100644 --- a/next/src/main/kotlin/org/fdroid/updates/AppUpdateWorker.kt +++ b/next/src/main/kotlin/org/fdroid/updates/AppUpdateWorker.kt @@ -17,8 +17,11 @@ import androidx.work.WorkManager import androidx.work.WorkerParameters import dagger.assisted.Assisted import dagger.assisted.AssistedInject +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.joinAll import mu.KotlinLogging import org.fdroid.NotificationManager import org.fdroid.NotificationManager.Companion.NOTIFICATION_ID_APP_INSTALLS @@ -96,14 +99,13 @@ class AppUpdateWorker @AssistedInject constructor( log.error(e) { "Error while running setForeground: " } } return try { + currentCoroutineContext().ensureActive() nm.cancelAppUpdatesAvailableNotification() // Updating apps will try start a foreground service // and it will "share" the same notification. // This is easier than trying to tell the [AppInstallManager] // not to start a foreground service in this specific case. - updatesManager.updateAll().forEach { job -> - job.join() - } + updatesManager.updateAll().joinAll() // show success notification, if at least one app got installed val notificationState = appInstallManager.installNotificationState if (notificationState.numInstalled > 0) { diff --git a/next/src/main/kotlin/org/fdroid/updates/UpdatesManager.kt b/next/src/main/kotlin/org/fdroid/updates/UpdatesManager.kt index d4c0e2760..5a65cd5a4 100644 --- a/next/src/main/kotlin/org/fdroid/updates/UpdatesManager.kt +++ b/next/src/main/kotlin/org/fdroid/updates/UpdatesManager.kt @@ -5,6 +5,8 @@ import androidx.core.os.LocaleListCompat import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job +import kotlinx.coroutines.currentCoroutineContext +import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.first @@ -117,10 +119,12 @@ class UpdatesManager @Inject constructor( val concurrencyLimit = min(Runtime.getRuntime().availableProcessors(), 8) val semaphore = Semaphore(concurrencyLimit) return appsToUpdate.map { update -> + currentCoroutineContext().ensureActive() // launch a new co-routine for each app to update coroutineScope.launch { // suspend here until we get a permit from the semaphore (there's free workers) semaphore.withPermit { + currentCoroutineContext().ensureActive() updateApp(update, canAskPreApprovalNow) } }