Loading app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.kt +3 −47 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ open class CalendarsSyncAdapterService : SyncAdapterService() { - this is is an automatic sync (i.e. manual syncs are run regardless of sync conditions) */ if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(accountSettings)) { !checkSyncConditions(accountSettings) ) { return } Loading Loading @@ -86,52 +87,7 @@ open class CalendarsSyncAdapterService : SyncAdapterService() { authority, syncResult, calendar ).let { val authState = accountSettings.credentials().authState if (authState != null) { if (authState.needsTokenRefresh) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest( tokenRequest, clientSecret ) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) it.accountSettings.credentials( Credentials( it.account.name, null, authState, null, clientSecret = clientSecretString ) ) object : AsyncTask<Void, Void, Void>() { override fun doInBackground(vararg params: Void): Void? { it.performSyncWithRetry() return null } }.execute() } } else { it.performSyncWithRetry() } } else { it.performSyncWithRetry() } } ).performSync() } } catch (e: Exception) { Logger.log.log(Level.SEVERE, "Couldn't sync calendars", e) Loading app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncAdapterService.kt +1 −42 Original line number Diff line number Diff line Loading @@ -67,48 +67,7 @@ open class ContactsSyncAdapterService: SyncAdapterService() { Logger.log.info("Synchronizing address book: ${addressBook.url}") Logger.log.info("Taking settings from: ${addressBook.mainAccount}") ContactsSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, provider, addressBook).let { val authState = accountSettings.credentials().authState if (authState != null) { if (authState.needsTokenRefresh) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) it.accountSettings.credentials( Credentials( it.account.name, null, authState, null, clientSecret = clientSecretString ) ) object : AsyncTask<Void, Void, Void>() { override fun doInBackground(vararg params: Void): Void? { it.performSyncWithRetry() return null } }.execute() } } else { it.performSyncWithRetry() } } else { it.performSyncWithRetry() } } ContactsSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, provider, addressBook).performSync() } catch(e: Exception) { Logger.log.log(Level.SEVERE, "Couldn't sync contacts", e) } Loading app/src/main/java/at/bitfire/davdroid/syncadapter/JtxSyncAdapterService.kt +1 −3 Original line number Diff line number Diff line Loading @@ -68,9 +68,7 @@ class JtxSyncAdapterService: SyncAdapterService() { val collections = JtxCollection.find(account, provider, context, LocalJtxCollection.Factory, null, null) for (collection in collections) { Logger.log.info("Synchronizing $collection") JtxSyncManager(context, account, accountSettings, extras, httpClient.value, authority, syncResult, collection).let { it.performSync() } JtxSyncManager(context, account, accountSettings, extras, httpClient.value, authority, syncResult, collection).performSync() } } catch (e: TaskProvider.ProviderTooOldException) { Loading app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt +53 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import at.bitfire.dav4jvm.property.ScheduleTag import at.bitfire.dav4jvm.property.SyncToken import at.bitfire.davdroid.* import at.bitfire.davdroid.db.AppDatabase import at.bitfire.davdroid.db.Credentials import at.bitfire.davdroid.db.SyncState import at.bitfire.davdroid.db.SyncStats import at.bitfire.davdroid.log.Logger Loading @@ -44,6 +45,8 @@ import dagger.hilt.InstallIn import dagger.hilt.android.EntryPointAccessors import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.* import net.openid.appauth.AuthState import net.openid.appauth.AuthorizationService import okhttp3.HttpUrl import okhttp3.RequestBody import org.apache.commons.io.FileUtils Loading @@ -56,6 +59,7 @@ import java.net.ConnectException import java.net.HttpURLConnection import java.security.cert.CertificateException import java.util.* import java.util.concurrent.Executors import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit Loading @@ -75,6 +79,8 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L val localCollection: CollectionType ) { private val executor = Executors.newSingleThreadExecutor() @EntryPoint @InstallIn(SingletonComponent::class) interface SyncManagerEntryPoint { Loading @@ -90,6 +96,10 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L const val DEBUG_INFO_MAX_RESOURCE_DUMP_SIZE = 100*FileUtils.ONE_KB.toInt() const val MAX_MULTIGET_RESOURCES = 10 const val DEFAULT_RETRY_AFTER = 5 const val DEFAULT_SECOND_RETRY_AFTER = 8 const val DEFAULT_MAX_RETRY_TIME = 21 var _workDispatcher: WeakReference<CoroutineDispatcher>? = null /** * We use our own dispatcher to Loading Loading @@ -135,8 +145,48 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L /** * Call performSync with default retry values */ fun performSyncWithRetry() { performSync(5, 8, 21) fun performSync() { val authState = accountSettings.credentials().authState if (authState == null || !authState.needsTokenRefresh) { performSync(DEFAULT_RETRY_AFTER, DEFAULT_SECOND_RETRY_AFTER, DEFAULT_MAX_RETRY_TIME) return } refreshAuthTokenAndSync(authState) } private fun refreshAuthTokenAndSync(authState: AuthState) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) executor.execute { performSync(DEFAULT_RETRY_AFTER, DEFAULT_SECOND_RETRY_AFTER, DEFAULT_MAX_RETRY_TIME) } } } /** Loading @@ -146,7 +196,7 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L * @param secondRetryAfter optional param, in seconds. Used to calculate fibonnacci sequence for rety on unhandled exception * @param maxRetryTime optional param, in seconds. On unhandled exception, max time the method should retry. */ fun performSync(retryAfter: Int = Int.MIN_VALUE, secondRetryAfter: Int = Int.MIN_VALUE, maxRetryTime: Int = Int.MIN_VALUE) { fun performSync(retryAfter: Int, secondRetryAfter: Int, maxRetryTime: Int) { // dismiss previous error notifications notificationManager.cancel(notificationTag, NotificationUtils.NOTIFY_SYNC_ERROR) Loading app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncAdapterService.kt +1 −43 Original line number Diff line number Diff line Loading @@ -73,49 +73,7 @@ open class TasksSyncAdapterService: SyncAdapterService() { .sortedByDescending { priorityTaskLists.contains(it.id) } for (taskList in taskLists) { Logger.log.info("Synchronizing task list #${taskList.id} [${taskList.syncId}]") TasksSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, taskList).let { val authState = accountSettings.credentials().authState if (authState != null) { if (authState.needsTokenRefresh) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) it.accountSettings.credentials( Credentials( it.account.name, null, authState, null, clientSecret = clientSecretString ) ) object : AsyncTask<Void, Void, Void>() { override fun doInBackground(vararg params: Void): Void? { it.performSyncWithRetry() return null } }.execute() } } else { it.performSyncWithRetry() } } else { it.performSyncWithRetry() } } TasksSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, taskList).performSync() } } catch (e: TaskProvider.ProviderTooOldException) { SyncUtils.notifyProviderTooOld(context, e) Loading Loading
app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.kt +3 −47 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ open class CalendarsSyncAdapterService : SyncAdapterService() { - this is is an automatic sync (i.e. manual syncs are run regardless of sync conditions) */ if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(accountSettings)) { !checkSyncConditions(accountSettings) ) { return } Loading Loading @@ -86,52 +87,7 @@ open class CalendarsSyncAdapterService : SyncAdapterService() { authority, syncResult, calendar ).let { val authState = accountSettings.credentials().authState if (authState != null) { if (authState.needsTokenRefresh) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest( tokenRequest, clientSecret ) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) it.accountSettings.credentials( Credentials( it.account.name, null, authState, null, clientSecret = clientSecretString ) ) object : AsyncTask<Void, Void, Void>() { override fun doInBackground(vararg params: Void): Void? { it.performSyncWithRetry() return null } }.execute() } } else { it.performSyncWithRetry() } } else { it.performSyncWithRetry() } } ).performSync() } } catch (e: Exception) { Logger.log.log(Level.SEVERE, "Couldn't sync calendars", e) Loading
app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncAdapterService.kt +1 −42 Original line number Diff line number Diff line Loading @@ -67,48 +67,7 @@ open class ContactsSyncAdapterService: SyncAdapterService() { Logger.log.info("Synchronizing address book: ${addressBook.url}") Logger.log.info("Taking settings from: ${addressBook.mainAccount}") ContactsSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, provider, addressBook).let { val authState = accountSettings.credentials().authState if (authState != null) { if (authState.needsTokenRefresh) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) it.accountSettings.credentials( Credentials( it.account.name, null, authState, null, clientSecret = clientSecretString ) ) object : AsyncTask<Void, Void, Void>() { override fun doInBackground(vararg params: Void): Void? { it.performSyncWithRetry() return null } }.execute() } } else { it.performSyncWithRetry() } } else { it.performSyncWithRetry() } } ContactsSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, provider, addressBook).performSync() } catch(e: Exception) { Logger.log.log(Level.SEVERE, "Couldn't sync contacts", e) } Loading
app/src/main/java/at/bitfire/davdroid/syncadapter/JtxSyncAdapterService.kt +1 −3 Original line number Diff line number Diff line Loading @@ -68,9 +68,7 @@ class JtxSyncAdapterService: SyncAdapterService() { val collections = JtxCollection.find(account, provider, context, LocalJtxCollection.Factory, null, null) for (collection in collections) { Logger.log.info("Synchronizing $collection") JtxSyncManager(context, account, accountSettings, extras, httpClient.value, authority, syncResult, collection).let { it.performSync() } JtxSyncManager(context, account, accountSettings, extras, httpClient.value, authority, syncResult, collection).performSync() } } catch (e: TaskProvider.ProviderTooOldException) { Loading
app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.kt +53 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import at.bitfire.dav4jvm.property.ScheduleTag import at.bitfire.dav4jvm.property.SyncToken import at.bitfire.davdroid.* import at.bitfire.davdroid.db.AppDatabase import at.bitfire.davdroid.db.Credentials import at.bitfire.davdroid.db.SyncState import at.bitfire.davdroid.db.SyncStats import at.bitfire.davdroid.log.Logger Loading @@ -44,6 +45,8 @@ import dagger.hilt.InstallIn import dagger.hilt.android.EntryPointAccessors import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.* import net.openid.appauth.AuthState import net.openid.appauth.AuthorizationService import okhttp3.HttpUrl import okhttp3.RequestBody import org.apache.commons.io.FileUtils Loading @@ -56,6 +59,7 @@ import java.net.ConnectException import java.net.HttpURLConnection import java.security.cert.CertificateException import java.util.* import java.util.concurrent.Executors import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit Loading @@ -75,6 +79,8 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L val localCollection: CollectionType ) { private val executor = Executors.newSingleThreadExecutor() @EntryPoint @InstallIn(SingletonComponent::class) interface SyncManagerEntryPoint { Loading @@ -90,6 +96,10 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L const val DEBUG_INFO_MAX_RESOURCE_DUMP_SIZE = 100*FileUtils.ONE_KB.toInt() const val MAX_MULTIGET_RESOURCES = 10 const val DEFAULT_RETRY_AFTER = 5 const val DEFAULT_SECOND_RETRY_AFTER = 8 const val DEFAULT_MAX_RETRY_TIME = 21 var _workDispatcher: WeakReference<CoroutineDispatcher>? = null /** * We use our own dispatcher to Loading Loading @@ -135,8 +145,48 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L /** * Call performSync with default retry values */ fun performSyncWithRetry() { performSync(5, 8, 21) fun performSync() { val authState = accountSettings.credentials().authState if (authState == null || !authState.needsTokenRefresh) { performSync(DEFAULT_RETRY_AFTER, DEFAULT_SECOND_RETRY_AFTER, DEFAULT_MAX_RETRY_TIME) return } refreshAuthTokenAndSync(authState) } private fun refreshAuthTokenAndSync(authState: AuthState) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) executor.execute { performSync(DEFAULT_RETRY_AFTER, DEFAULT_SECOND_RETRY_AFTER, DEFAULT_MAX_RETRY_TIME) } } } /** Loading @@ -146,7 +196,7 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L * @param secondRetryAfter optional param, in seconds. Used to calculate fibonnacci sequence for rety on unhandled exception * @param maxRetryTime optional param, in seconds. On unhandled exception, max time the method should retry. */ fun performSync(retryAfter: Int = Int.MIN_VALUE, secondRetryAfter: Int = Int.MIN_VALUE, maxRetryTime: Int = Int.MIN_VALUE) { fun performSync(retryAfter: Int, secondRetryAfter: Int, maxRetryTime: Int) { // dismiss previous error notifications notificationManager.cancel(notificationTag, NotificationUtils.NOTIFY_SYNC_ERROR) Loading
app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncAdapterService.kt +1 −43 Original line number Diff line number Diff line Loading @@ -73,49 +73,7 @@ open class TasksSyncAdapterService: SyncAdapterService() { .sortedByDescending { priorityTaskLists.contains(it.id) } for (taskList in taskLists) { Logger.log.info("Synchronizing task list #${taskList.id} [${taskList.syncId}]") TasksSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, taskList).let { val authState = accountSettings.credentials().authState if (authState != null) { if (authState.needsTokenRefresh) { val tokenRequest = authState.createTokenRefreshRequest() val clientSecretString = accountSettings.credentials().clientSecret val clientSecret = OpenIdUtils.getClientAuthentication(clientSecretString) AuthorizationService(context).performTokenRequest(tokenRequest, clientSecret) { tokenResponse, ex -> authState.update(tokenResponse, ex) accountSettings.credentials( Credentials( account.name, null, authState, null, clientSecret = clientSecretString ) ) it.accountSettings.credentials( Credentials( it.account.name, null, authState, null, clientSecret = clientSecretString ) ) object : AsyncTask<Void, Void, Void>() { override fun doInBackground(vararg params: Void): Void? { it.performSyncWithRetry() return null } }.execute() } } else { it.performSyncWithRetry() } } else { it.performSyncWithRetry() } } TasksSyncManager(context, account, accountSettings, httpClient.value, extras, authority, syncResult, taskList).performSync() } } catch (e: TaskProvider.ProviderTooOldException) { SyncUtils.notifyProviderTooOld(context, e) Loading