diff --git a/app/core/src/main/java/com/fsck/k9/Account.kt b/app/core/src/main/java/com/fsck/k9/Account.kt index f3906ab6abca857bd9378670943699c059a417bc..71d4d6fc040e1ee3206b7e67e95a5a52efd6a2ff 100644 --- a/app/core/src/main/java/com/fsck/k9/Account.kt +++ b/app/core/src/main/java/com/fsck/k9/Account.kt @@ -360,10 +360,6 @@ class Account(override val uuid: String) : BaseAccount { @set:Synchronized var messagesNotificationChannelVersion = 0 - @get:Synchronized - @set:Synchronized - var backgroundSync = true - @get:Synchronized @set:Synchronized var isChangedVisibleLimits = false diff --git a/app/core/src/main/java/com/fsck/k9/AccountPreferenceSerializer.kt b/app/core/src/main/java/com/fsck/k9/AccountPreferenceSerializer.kt index 4851915118773e86eeb2c0bf9d3515c7d3a2965b..e827460425df7812d20e08dc42929e8148fee139 100644 --- a/app/core/src/main/java/com/fsck/k9/AccountPreferenceSerializer.kt +++ b/app/core/src/main/java/com/fsck/k9/AccountPreferenceSerializer.kt @@ -54,7 +54,6 @@ class AccountPreferenceSerializer( isIgnoreChatMessages = storage.getBoolean("$accountUuid.ignoreChatMessages", false) isNotifySync = storage.getBoolean("$accountUuid.notifyMailCheck", false) messagesNotificationChannelVersion = storage.getInt("$accountUuid.messagesNotificationChannelVersion", 0) - backgroundSync = storage.getBoolean("$accountUuid.backgroundSync", true) deletePolicy = DeletePolicy.fromInt(storage.getInt("$accountUuid.deletePolicy", DeletePolicy.NEVER.setting)) legacyInboxFolder = storage.getString("$accountUuid.inboxFolderName", null) importedDraftsFolder = storage.getString("$accountUuid.draftsFolderName", null) @@ -260,7 +259,6 @@ class AccountPreferenceSerializer( editor.putBoolean("$accountUuid.ignoreChatMessages", isIgnoreChatMessages) editor.putBoolean("$accountUuid.notifyMailCheck", isNotifySync) editor.putInt("$accountUuid.messagesNotificationChannelVersion", messagesNotificationChannelVersion) - editor.putBoolean("$accountUuid.backgroundSync", backgroundSync) editor.putInt("$accountUuid.deletePolicy", deletePolicy.setting) editor.putString("$accountUuid.inboxFolderName", legacyInboxFolder) editor.putString("$accountUuid.draftsFolderName", importedDraftsFolder) @@ -551,7 +549,6 @@ class AccountPreferenceSerializer( isNotifyContactsMailOnly = false isIgnoreChatMessages = false messagesNotificationChannelVersion = 0 - backgroundSync = true folderDisplayMode = FolderMode.NOT_SECOND_CLASS folderSyncMode = FolderMode.FIRST_CLASS folderPushMode = FolderMode.ALL diff --git a/app/core/src/main/java/com/fsck/k9/OsAccountManagerUtil.kt b/app/core/src/main/java/com/fsck/k9/OsAccountManagerUtil.kt new file mode 100644 index 0000000000000000000000000000000000000000..9229ca256520e8bb69897b7f022fb4e189c66e56 --- /dev/null +++ b/app/core/src/main/java/com/fsck/k9/OsAccountManagerUtil.kt @@ -0,0 +1,81 @@ +/* + * Copyright MURENA SAS 2022 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.fsck.k9 + +import android.accounts.Account +import android.accounts.AccountManager +import android.content.ContentResolver +import android.content.Context +import com.fsck.k9.setup.AccountManagerConstants +import timber.log.Timber + +object OsAccountManagerUtil { + + /** + * @return syncEnable or not. If account not found in accountManager accounts, + * means account is setup by user... so return true by default + */ + fun isSyncEnable(context: Context, email: String): Boolean { + val accountManager = AccountManager.get(context) + + val murenaAccounts = accountManager.getAccountsByType(AccountManagerConstants.EELO_ACCOUNT_TYPE) + var syncEnable = isSyncEnable(accountManager, murenaAccounts, email) + if (syncEnable.isAccountFound()) { + return syncEnable.getStatus() + } + + val googleAccounts = accountManager.getAccountsByType(AccountManagerConstants.GOOGLE_ACCOUNT_TYPE) + syncEnable = isSyncEnable(accountManager, googleAccounts, email) + if (syncEnable.isAccountFound()) { + return syncEnable.getStatus() + } + + return true + } + + private fun isSyncEnable(accountManager: AccountManager, accounts: Array, email: String): Syncable { + accounts.forEach { + try { + val accountEmail: String = accountManager.getUserData(it, AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY) + if (accountEmail == email) { + // if master sync disable, then account sync is disable + return if (!ContentResolver.getMasterSyncAutomatically()) { + Syncable.NOT_SYNCABLE + } else Syncable.getSyncable(ContentResolver.getSyncAutomatically(it, AccountManagerConstants.MAIL_CONTENT_AUTHORITY)) + } + } catch (e: Throwable) { + Timber.e(e) + } + } + + return Syncable.ACCOUNT_NOT_FOUND + } + + private enum class Syncable { + SYNCABLE, + NOT_SYNCABLE, + ACCOUNT_NOT_FOUND; + + companion object { + fun getSyncable(status: Boolean) = if (status) SYNCABLE else NOT_SYNCABLE + } + + fun getStatus() = this == SYNCABLE + + fun isAccountFound() = this != ACCOUNT_NOT_FOUND + } +} \ No newline at end of file diff --git a/app/core/src/main/java/com/fsck/k9/controller/push/KoinModule.kt b/app/core/src/main/java/com/fsck/k9/controller/push/KoinModule.kt index b8046a970d17294f86a7eb44f5c583121a8a95d3..86b0ae1227472ca8d155a618ca54c9ef49b11666 100644 --- a/app/core/src/main/java/com/fsck/k9/controller/push/KoinModule.kt +++ b/app/core/src/main/java/com/fsck/k9/controller/push/KoinModule.kt @@ -24,7 +24,8 @@ internal val controllerPushModule = module { autoSyncManager = get(), pushNotificationManager = get(), connectivityManager = get(), - accountPushControllerFactory = get() + accountPushControllerFactory = get(), + context = get() ) } } diff --git a/app/core/src/main/java/com/fsck/k9/controller/push/PushController.kt b/app/core/src/main/java/com/fsck/k9/controller/push/PushController.kt index a47dd70189094b6c4eec27046c71674a7f7a0d73..206ae842219977907acef7df96fe2b88d8ab62b9 100644 --- a/app/core/src/main/java/com/fsck/k9/controller/push/PushController.kt +++ b/app/core/src/main/java/com/fsck/k9/controller/push/PushController.kt @@ -1,7 +1,9 @@ package com.fsck.k9.controller.push +import android.content.Context import com.fsck.k9.Account import com.fsck.k9.Account.FolderMode +import com.fsck.k9.OsAccountManagerUtil import com.fsck.k9.Preferences import com.fsck.k9.backend.BackendManager import com.fsck.k9.network.ConnectivityChangeListener @@ -39,7 +41,8 @@ class PushController internal constructor( private val connectivityManager: ConnectivityManager, private val accountPushControllerFactory: AccountPushControllerFactory, private val coroutineScope: CoroutineScope = GlobalScope, - private val coroutineDispatcher: CoroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + private val coroutineDispatcher: CoroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher(), + private val context: Context ) { private val lock = Any() private var initializationStarted = false @@ -211,7 +214,7 @@ class PushController internal constructor( private fun getPushAccounts(): List { return preferences.accounts.filter { account -> - account.folderPushMode != FolderMode.NONE && account.backgroundSync && backendManager.getBackend(account)?.isPushCapable ?: false + account.folderPushMode != FolderMode.NONE && OsAccountManagerUtil.isSyncEnable(context, account.email) && backendManager.getBackend(account)?.isPushCapable ?: false } } private fun setPushNotificationState(notificationState: PushNotificationState) { diff --git a/app/core/src/main/java/com/fsck/k9/job/KoinModule.kt b/app/core/src/main/java/com/fsck/k9/job/KoinModule.kt index 4dd6f0e8fa3e15d5916db695765b0a70583fd8fa..40df51b649e9eceafd986422212c457fecd68336 100644 --- a/app/core/src/main/java/com/fsck/k9/job/KoinModule.kt +++ b/app/core/src/main/java/com/fsck/k9/job/KoinModule.kt @@ -8,5 +8,5 @@ val jobModule = module { single { K9WorkerFactory(get(), get()) } single { get().getWorkManager() } single { K9JobManager(get(), get(), get()) } - factory { MailSyncWorkerManager(workManager = get(), clock = get()) } + factory { MailSyncWorkerManager(workManager = get(), clock = get(), context = get()) } } diff --git a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt index 057fa690927ed26d082aca6f24ebacd53e6404af..e39d6404d3ec1b89e23a048f87bf427980914a39 100644 --- a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt +++ b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorker.kt @@ -6,6 +6,7 @@ import androidx.work.Worker import androidx.work.WorkerParameters import com.fsck.k9.Account import com.fsck.k9.K9 +import com.fsck.k9.OsAccountManagerUtil import com.fsck.k9.Preferences import com.fsck.k9.controller.MessagingController import com.fsck.k9.mail.AuthType @@ -41,7 +42,7 @@ class MailSyncWorker( return Result.success() } - if (!account.backgroundSync) { + if (!OsAccountManagerUtil.isSyncEnable(context, account.email)) { Timber.d("Mail sync is disable for this account. Skipping mail sync.") return Result.success() } diff --git a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorkerManager.kt b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorkerManager.kt index 87df71d0c14d93c4b47599d0d02142620b5c679b..81e655fa0a179cf31bfc94010307ecd3c10271b2 100644 --- a/app/core/src/main/java/com/fsck/k9/job/MailSyncWorkerManager.kt +++ b/app/core/src/main/java/com/fsck/k9/job/MailSyncWorkerManager.kt @@ -1,5 +1,6 @@ package com.fsck.k9.job +import android.content.Context import androidx.work.BackoffPolicy import androidx.work.Constraints import androidx.work.ExistingPeriodicWorkPolicy @@ -10,10 +11,11 @@ import androidx.work.workDataOf import com.fsck.k9.Account import com.fsck.k9.Clock import com.fsck.k9.K9 +import com.fsck.k9.OsAccountManagerUtil import java.util.concurrent.TimeUnit import timber.log.Timber -class MailSyncWorkerManager(private val workManager: WorkManager, val clock: Clock) { +class MailSyncWorkerManager(private val workManager: WorkManager, val clock: Clock, private val context: Context) { fun cancelMailSync(account: Account) { Timber.v("Canceling mail sync worker for %s", account) @@ -24,7 +26,7 @@ class MailSyncWorkerManager(private val workManager: WorkManager, val clock: Clo fun scheduleMailSync(account: Account) { if (isNeverSyncInBackground()) return - if (!account.backgroundSync) { + if (!OsAccountManagerUtil.isSyncEnable(context, account.email)) { return } diff --git a/app/k9mail/src/main/AndroidManifest.xml b/app/k9mail/src/main/AndroidManifest.xml index c6fccb39d3025881daa275b4cd4a69d76cb50a26..4100e6b82dc1331c2847fdbe8d7d991b418e8b0c 100644 --- a/app/k9mail/src/main/AndroidManifest.xml +++ b/app/k9mail/src/main/AndroidManifest.xml @@ -329,8 +329,7 @@ android:exported="true"> - - + diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/account/AccountSyncReceiver.kt b/app/ui/legacy/src/main/java/com/fsck/k9/account/AccountSyncReceiver.kt index 6a79dce9091c8e9c409684029979d11cfebd0c80..a1f9617c8019569988fd36bdac4fda6c9b5250a4 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/account/AccountSyncReceiver.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/account/AccountSyncReceiver.kt @@ -16,6 +16,7 @@ package com.fsck.k9.account +import android.accounts.AccountManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -24,9 +25,11 @@ import com.fsck.k9.Preferences import com.fsck.k9.activity.setup.accountmanager.EeloAccountCreator import com.fsck.k9.controller.push.PushController import com.fsck.k9.job.K9JobManager +import com.fsck.k9.setup.AccountManagerConstants import java.util.concurrent.Executors import org.koin.core.component.KoinComponent import org.koin.core.component.inject +import timber.log.Timber class AccountSyncReceiver : BroadcastReceiver(), KoinComponent { @@ -34,10 +37,9 @@ class AccountSyncReceiver : BroadcastReceiver(), KoinComponent { private const val ACTION_PREFIX = "foundation.e.accountmanager.account" private const val ACCOUNT_CREATION_ACTION = "$ACTION_PREFIX.create" - private const val ACCOUNT_REMOVAL_ACTION = "$ACTION_PREFIX.remove" - private const val ACCOUNT_DISABLE_SYNC_ACTION = "$ACTION_PREFIX.disablesync" + private const val ACCOUNT_REMOVAL_ACTION = "android.accounts.action.ACCOUNT_REMOVED" - private const val ACCOUNT = "account" + private val ACCOUNT_TYPES = listOf(AccountManagerConstants.EELO_ACCOUNT_TYPE, AccountManagerConstants.GOOGLE_ACCOUNT_TYPE) } private val pushController: PushController by inject() @@ -53,7 +55,6 @@ class AccountSyncReceiver : BroadcastReceiver(), KoinComponent { when (intent.action) { ACCOUNT_CREATION_ACTION -> createNewAccount(context) ACCOUNT_REMOVAL_ACTION -> removeAccount(intent) - ACCOUNT_DISABLE_SYNC_ACTION -> disableSync(intent) } } @@ -77,16 +78,14 @@ class AccountSyncReceiver : BroadcastReceiver(), KoinComponent { accountRemover.removeAccountAsync(account.uuid) } - private fun disableSync(intent: Intent) { - val account = getAccount(intent) ?: return - account.backgroundSync = false - preferences.saveAccount(account) - jobManager.scheduleAllMailJobs() - } + private fun getAccount(intent: Intent) : Account? { + val accountType = intent.extras?.getString(AccountManager.KEY_ACCOUNT_TYPE) + if (!ACCOUNT_TYPES.contains(accountType)) { + return null + } - private fun getAccount(intent: Intent) : Account? { - val account = intent.extras?.getString(ACCOUNT) ?: return null + val account = intent.extras?.getString(AccountManager.KEY_ACCOUNT_NAME) ?: return null preferences.accounts.forEach { if (it.email == account) { diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/accountmanager/EeloAccountCreator.java b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/accountmanager/EeloAccountCreator.java index da1d29a030c86514cff293414fc1898d1f572689..897b21dd3d8ea3b89be27c779d11cf4f6d601a67 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/accountmanager/EeloAccountCreator.java +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/accountmanager/EeloAccountCreator.java @@ -115,7 +115,7 @@ public class EeloAccountCreator { continue; } - enableSync(jobManager, existenceAccount.get()); + jobManager.scheduleAllMailJobs(); } } @@ -155,22 +155,10 @@ public class EeloAccountCreator { continue; } - enableSync(jobManager, existenceAccount.get()); + jobManager.scheduleAllMailJobs(); } } - // enable account sync if not already enabled - private static void enableSync(@NonNull K9JobManager jobManager, @NonNull Account account) { - // sync is already enabled, ignore - if (account.getBackgroundSync()) { - return; - } - - account.setBackgroundSync(true); - Preferences.getPreferences().saveAccount(account); - jobManager.scheduleAllMailJobs(); - } - @RequiresApi(api = VERSION_CODES.N) private static void deleteIncompleteAccounts(List accounts, BackgroundAccountRemover accountRemover) { accounts.stream().filter(account -> !account.isFinishedSetup())