From d261dd705d51928141fd07da0ee38c0ccd59083d Mon Sep 17 00:00:00 2001 From: Andrew Aylett Date: Sun, 31 Jan 2021 18:13:53 +0000 Subject: [PATCH 01/16] 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? } From e14fb16db2f193e8cb53899cc698bfc45a5a04f9 Mon Sep 17 00:00:00 2001 From: Marcel Langner Date: Fri, 13 Aug 2021 12:29:11 +0200 Subject: [PATCH 02/16] initial commit of a permanent GuardService for fdroid background syncing --- .../util/BackgroundDetectionObserver.kt | 2 +- vector/src/fdroid/AndroidManifest.xml | 7 + .../app/fdroid/BackgroundSyncStarter.kt | 22 ++- .../vector/app/fdroid/service/GuardService.kt | 156 ++++++++++++++++++ 4 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 vector/src/fdroid/java/im/vector/app/fdroid/service/GuardService.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt index 7cc00d023f..a12587ac56 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt @@ -29,7 +29,7 @@ import javax.inject.Inject @MatrixScope internal class BackgroundDetectionObserver @Inject constructor() : LifecycleObserver { - var isInBackground: Boolean = false + var isInBackground: Boolean = true private set private diff --git a/vector/src/fdroid/AndroidManifest.xml b/vector/src/fdroid/AndroidManifest.xml index 3a7c107138..022b08f16d 100644 --- a/vector/src/fdroid/AndroidManifest.xml +++ b/vector/src/fdroid/AndroidManifest.xml @@ -1,9 +1,11 @@ +