diff --git a/app/src/androidTestOse/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorkerTest.kt b/app/src/androidTestOse/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorkerTest.kt index c54e9669..2de4db2b 100644 --- a/app/src/androidTestOse/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorkerTest.kt +++ b/app/src/androidTestOse/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorkerTest.kt @@ -24,7 +24,6 @@ import at.bitfire.davdroid.ui.NotificationUtils import at.bitfire.ical4android.TaskProvider import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest -import org.junit.After import org.junit.AfterClass import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -97,6 +96,28 @@ class PeriodicSyncWorkerTest { assertFalse(workScheduledOrRunning(context, workerName)) } + @Test + fun doWork_cancelsItselfOnInvalidAccount() { + val invalidAccount = Account("invalid", context.getString(R.string.account_type)) + val authority = CalendarContract.AUTHORITY + + // Enable the PeriodicSyncWorker + PeriodicSyncWorker.enable(context, invalidAccount, authority, 15*60, false) + assertTrue(workScheduledOrRunning(context, PeriodicSyncWorker.workerName(account, authority))) + + // Run PeriodicSyncWorker as TestWorker + val inputData = workDataOf( + PeriodicSyncWorker.ARG_AUTHORITY to authority, + PeriodicSyncWorker.ARG_ACCOUNT_NAME to invalidAccount.name, + PeriodicSyncWorker.ARG_ACCOUNT_TYPE to invalidAccount.type + ) + val result = TestWorkerBuilder(context, executor, inputData).build().doWork() + + // Verify that the PeriodicSyncWorker cancelled itself + assertTrue(result is androidx.work.ListenableWorker.Result.Failure) + assertFalse(workScheduledOrRunning(context, PeriodicSyncWorker.workerName(invalidAccount, authority))) + } + @Test fun doWork_immediatelyEnqueuesSyncWorkerForGivenAuthority() { val authorities = listOf( diff --git a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorker.kt b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorker.kt index ef1a4291..0aca6d89 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorker.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/PeriodicSyncWorker.kt @@ -17,6 +17,7 @@ import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkManager import androidx.work.Worker import androidx.work.WorkerParameters +import at.bitfire.davdroid.InvalidAccountException import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.settings.AccountSettings import dagger.assisted.Assisted @@ -117,7 +118,13 @@ class PeriodicSyncWorker @AssistedInject constructor( val authority = inputData.getString(ARG_AUTHORITY) ?: throw IllegalArgumentException("$ARG_AUTHORITY required") Logger.log.info("Running periodic sync worker: account=$account, authority=$authority") - val accountSettings = AccountSettings(applicationContext, account) + val accountSettings = try { + AccountSettings(applicationContext, account) + } catch (e: InvalidAccountException) { + Logger.log.warning("Account $account doesn't exist anymore, cancelling periodic sync") + disable(applicationContext, account, authority) + return Result.failure() + } if (!SyncWorker.wifiConditionsMet(applicationContext, accountSettings)) { Logger.log.info("Sync conditions not met. Won't run sync.") return Result.failure() diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt index d63004ac..f4176840 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt @@ -49,6 +49,7 @@ import at.bitfire.davdroid.resource.LocalAddressBook import at.bitfire.davdroid.resource.LocalTaskList import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.AccountsCleanupWorker +import at.bitfire.davdroid.syncadapter.PeriodicSyncWorker import at.bitfire.davdroid.syncadapter.SyncWorker import at.bitfire.ical4android.TaskProvider import com.google.accompanist.themeadapter.material.MdcTheme @@ -207,6 +208,13 @@ class RenameAccountFragment: DialogFragment() { } } + /** + * Called when an account has been renamed. + * + * @param oldAccount the old account + * @param newName the new account + * @param syncIntervals map with entries of type (authority -> sync interval) of the old account + */ @SuppressLint("Recycle") @WorkerThread fun onAccountRenamed(accountManager: AccountManager, oldAccount: Account, newName: String, syncIntervals: List>) { @@ -214,6 +222,11 @@ class RenameAccountFragment: DialogFragment() { Logger.log.info("Updating account name references") val context: Application = getApplication() + // disable periodic workers of old account + syncIntervals.forEach { (authority, _) -> + PeriodicSyncWorker.disable(context, oldAccount, authority) + } + // cancel maybe running synchronization SyncWorker.cancelSync(context, oldAccount) for (addrBookAccount in accountManager.getAccountsByType(context.getString(R.string.account_type_address_book)))