From d261dd705d51928141fd07da0ee38c0ccd59083d Mon Sep 17 00:00:00 2001 From: Andrew Aylett Date: Sun, 31 Jan 2021 18:13:53 +0000 Subject: [PATCH] Periodic sync to re-kick-off rapid sync --- .../matrix/android/sdk/api/session/Session.kt | 5 ++-- .../sdk/internal/di/WorkManagerProvider.kt | 10 +++++++ .../sdk/internal/session/DefaultSession.kt | 4 +-- .../internal/session/sync/job/SyncWorker.kt | 29 ++++++++++++++++--- .../app/fdroid/BackgroundSyncStarter.kt | 1 + .../java/im/vector/app/push/fcm/FcmHelper.kt | 7 ++++- .../features/call/webrtc/WebRtcCallManager.kt | 2 +- 7 files changed, 47 insertions(+), 11 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index d4bfd4ee8c..74b3876177 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -121,10 +121,9 @@ interface Session : /** * Launches infinite periodic background syncs - * This does not work in doze mode :/ - * If battery optimization is on it can work in app standby but that's all :/ + * Doze mode will probably interrupt rapid sync, but it should start up again the next time we run a periodic sync */ - fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long) + fun startAutomaticBackgroundSync(timeOutInSeconds: Long, rapidSync: Boolean, repeatDelayInSeconds: Long) fun stopAnyBackgroundSync() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt index bafffdf852..2fef48e17b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/WorkManagerProvider.kt @@ -50,6 +50,16 @@ internal class WorkManagerProvider @Inject constructor( PeriodicWorkRequestBuilder(repeatInterval, repeatIntervalTimeUnit) .addTag(tag) + /** + * Create a PeriodicWorkRequestBuilder, with the Matrix SDK tag + */ + inline fun matrixPeriodicWorkRequestBuilder(repeatInterval: Long, + repeatIntervalTimeUnit: TimeUnit, + flexTimeInterval: Long, + flexTimeIntervalUnit: TimeUnit) = + PeriodicWorkRequestBuilder(repeatInterval, repeatIntervalTimeUnit, flexTimeInterval, flexTimeIntervalUnit) + .addTag(tag) + /** * Cancel all works instantiated by the Matrix SDK for the current session, and not those from the SDK client, or for other sessions */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index c52462612a..8b89ee04cc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -184,8 +184,8 @@ internal class DefaultSession @Inject constructor( SyncWorker.requireBackgroundSync(workManagerProvider, sessionId) } - override fun startAutomaticBackgroundSync(timeOutInSeconds: Long, repeatDelayInSeconds: Long) { - SyncWorker.automaticallyBackgroundSync(workManagerProvider, sessionId, timeOutInSeconds, repeatDelayInSeconds) + override fun startAutomaticBackgroundSync(timeOutInSeconds: Long, rapidSync: Boolean, repeatDelayInSeconds: Long) { + SyncWorker.automaticallyPeriodicBackgroundSync(workManagerProvider, sessionId, timeOutInSeconds, rapidSync, repeatDelayInSeconds) } override fun stopAnyBackgroundSync() { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt index b81804feb5..bcc9f4d995 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncWorker.kt @@ -17,7 +17,9 @@ package org.matrix.android.sdk.internal.session.sync.job import android.content.Context import androidx.work.BackoffPolicy +import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingWorkPolicy +import androidx.work.WorkRequest import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.failure.isTokenError @@ -73,7 +75,7 @@ internal class SyncWorker(context: Context, Result.success().also { if (params.periodic) { // we want to schedule another one after delay - automaticallyBackgroundSync(workManagerProvider, params.sessionId, params.timeout, params.delay) + automaticallyRapidBackgroundSync(workManagerProvider, params.sessionId, params.timeout, params.delay) } } }, @@ -101,6 +103,8 @@ internal class SyncWorker(context: Context, companion object { private const val BG_SYNC_WORK_NAME = "BG_SYNCP" + private const val BG_RAPID_SYNC_WORK_NAME = "BG_RAPID_SYNCP" + private const val BG_PERIODIC_SYNC_WORK_NAME = "BG_PERIODIC_SYNCP" fun requireBackgroundSync(workManagerProvider: WorkManagerProvider, sessionId: String, serverTimeout: Long = 0) { val data = WorkerParamsFactory.toData(Params(sessionId, serverTimeout, 0L, false)) @@ -109,11 +113,12 @@ internal class SyncWorker(context: Context, .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) .setInputData(data) .build() + // If we've already scheduled a sync that's not yet run, defer to the existing one workManagerProvider.workManager - .enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest) + .enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.KEEP, workRequest) } - fun automaticallyBackgroundSync(workManagerProvider: WorkManagerProvider, sessionId: String, serverTimeout: Long = 0, delayInSeconds: Long = 30) { + fun automaticallyRapidBackgroundSync(workManagerProvider: WorkManagerProvider, sessionId: String, serverTimeout: Long = 0, delayInSeconds: Long = 30) { val data = WorkerParamsFactory.toData(Params(sessionId, serverTimeout, delayInSeconds, true)) val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder() .setConstraints(WorkManagerProvider.workConstraints) @@ -121,14 +126,30 @@ internal class SyncWorker(context: Context, .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) .setInitialDelay(delayInSeconds, TimeUnit.SECONDS) .build() + // Avoid risking multiple chains of syncs by replacing the existing chain + workManagerProvider.workManager + .enqueueUniqueWork(BG_RAPID_SYNC_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest) + } + + fun automaticallyPeriodicBackgroundSync(workManagerProvider: WorkManagerProvider, sessionId: String, serverTimeout: Long = 0, restartRapidSync: Boolean = true, delayInSeconds: Long = 30) { + val data = WorkerParamsFactory.toData(Params(sessionId, serverTimeout, delayInSeconds, restartRapidSync)) + val workRequest = workManagerProvider.matrixPeriodicWorkRequestBuilder(1, TimeUnit.HOURS, 15, TimeUnit.MINUTES) + .setConstraints(WorkManagerProvider.workConstraints) + .setInputData(data) + .setBackoffCriteria(BackoffPolicy.LINEAR, WorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) + .build() workManagerProvider.workManager - .enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest) + .enqueueUniquePeriodicWork(BG_PERIODIC_SYNC_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, workRequest) } fun stopAnyBackgroundSync(workManagerProvider: WorkManagerProvider) { workManagerProvider.workManager .cancelUniqueWork(BG_SYNC_WORK_NAME) + workManagerProvider.workManager + .cancelUniqueWork(BG_RAPID_SYNC_WORK_NAME) + workManagerProvider.workManager + .cancelUniqueWork(BG_PERIODIC_SYNC_WORK_NAME) } } } diff --git a/vector/src/fdroid/java/im/vector/app/fdroid/BackgroundSyncStarter.kt b/vector/src/fdroid/java/im/vector/app/fdroid/BackgroundSyncStarter.kt index 7221e2b065..46762f8be7 100644 --- a/vector/src/fdroid/java/im/vector/app/fdroid/BackgroundSyncStarter.kt +++ b/vector/src/fdroid/java/im/vector/app/fdroid/BackgroundSyncStarter.kt @@ -34,6 +34,7 @@ object BackgroundSyncStarter { Timber.i("## Sync: Work scheduled to periodically sync in ${vectorPreferences.backgroundSyncDelay()}s") activeSession.startAutomaticBackgroundSync( vectorPreferences.backgroundSyncTimeOut().toLong(), + true, vectorPreferences.backgroundSyncDelay().toLong() ) } diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt b/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt index fe091ffda3..d4f2b0dd57 100755 --- a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt @@ -108,6 +108,11 @@ object FcmHelper { @Suppress("UNUSED_PARAMETER") fun onEnterBackground(context: Context, vectorPreferences: VectorPreferences, activeSessionHolder: ActiveSessionHolder) { - // TODO FCM fallback + val activeSession = activeSessionHolder.getSafeActiveSession() ?: return + activeSession.startAutomaticBackgroundSync( + vectorPreferences.backgroundSyncTimeOut().toLong(), + false, + vectorPreferences.backgroundSyncDelay().toLong() + ) } } diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt index 9e620174f3..828dbc21e3 100644 --- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt +++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt @@ -373,7 +373,7 @@ class WebRtcCallManager @Inject constructor( if (isInBackground) { if (FcmHelper.isPushSupported()) { // only for push version as fdroid version is already doing it? - currentSession?.startAutomaticBackgroundSync(30, 0) + currentSession?.startAutomaticBackgroundSync(30, true, 0) } else { // Maybe increase sync freq? but how to set back to default values? }