Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95ecac88 authored by cketti's avatar cketti
Browse files

Close all Push connections when Android connects to another network

When the default network changes Android usually kills connections established over the old network after a little while. K-9 Mail treats this as a regular network error and sleeps for 5 minutes before trying to re-establish the Push connection(s). Closing old connections and opening new ones when a network change is detected avoids this error.
parent 830b358f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -49,6 +49,11 @@ internal class AccountPushController(
        stopBackendPusher()
    }

    fun reconnect() {
        Timber.v("AccountPushController(%s).reconnect()", account.uuid)
        backendPusher?.reconnect()
    }

    private fun startBackendPusher() {
        val backend = backendManager.getBackend(account)
        backendPusher = backend.createPusher(backendPusherCallback).also { backendPusher ->
+14 −3
Original line number Diff line number Diff line
@@ -13,10 +13,11 @@ import com.fsck.k9.notification.PushNotificationState.WAIT_BACKGROUND_SYNC
import com.fsck.k9.notification.PushNotificationState.WAIT_NETWORK
import com.fsck.k9.preferences.BackgroundSync
import com.fsck.k9.preferences.GeneralSettingsManager
import java.util.concurrent.Executors
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
@@ -38,7 +39,7 @@ class PushController internal constructor(
    private val connectivityManager: ConnectivityManager,
    private val accountPushControllerFactory: AccountPushControllerFactory,
    private val coroutineScope: CoroutineScope = GlobalScope,
    private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO
    private val coroutineDispatcher: CoroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
) {
    private val lock = Any()
    private var initializationStarted = false
@@ -47,7 +48,7 @@ class PushController internal constructor(
    private val autoSyncListener = AutoSyncListener(::onAutoSyncChanged)
    private val connectivityChangeListener = object : ConnectivityChangeListener {
        override fun onConnectivityChanged() = this@PushController.onConnectivityChanged()
        override fun onConnectivityLost() = this@PushController.onConnectivityChanged()
        override fun onConnectivityLost() = this@PushController.onConnectivityLost()
    }

    /**
@@ -98,6 +99,16 @@ class PushController internal constructor(
    }

    private fun onConnectivityChanged() {
        coroutineScope.launch(coroutineDispatcher) {
            synchronized(lock) {
                for (accountPushController in pushers.values) {
                    accountPushController.reconnect()
                }
            }
        }
    }

    private fun onConnectivityLost() {
        launchUpdatePushers()
    }

+1 −0
Original line number Diff line number Diff line
@@ -4,4 +4,5 @@ interface BackendPusher {
    fun start()
    fun updateFolders(folderServerIds: Collection<String>)
    fun stop()
    fun reconnect()
}
+20 −0
Original line number Diff line number Diff line
@@ -151,6 +151,26 @@ internal class ImapBackendPusher(
        }
    }

    override fun reconnect() {
        Timber.v("ImapBackendPusher.reconnect()")

        synchronized(lock) {
            for (pushFolder in pushFolders.values) {
                pushFolder.stop()
            }
            pushFolders.clear()

            for (retryTimer in pushFolderSleeping.values) {
                retryTimer.cancel()
            }
            pushFolderSleeping.clear()
        }

        imapStore.closeAllConnections()

        updateFolders()
    }

    private fun createImapFolderPusher(folderServerId: String): ImapFolderPusher {
        return ImapFolderPusher(
            imapStore,