From 494ad837041a48025128eda906be9a89e5f1aca7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 14 Jan 2020 15:06:19 +0100 Subject: [PATCH] Inject WorkManagerProvider, to avoid injecting the Android context Also ensure WorkManager uses a distinct tags for each session (for future multi-sessions support) --- .../verification/SasTransportRoomMessage.kt | 32 +++++----- .../internal/di/WorkManagerProvider.kt | 58 +++++++++++++++++++ .../internal/session/DefaultSession.kt | 10 ++-- .../session/group/GroupSummaryUpdater.kt | 13 ++--- .../session/pushers/DefaultPusherService.kt | 13 ++--- .../room/relation/DefaultRelationService.kt | 41 ++++++------- .../session/room/send/DefaultSendService.kt | 47 ++++++++------- .../timeline/TimelineSendEventWorkCommon.kt | 42 ++++++++------ .../internal/session/signout/SignOutTask.kt | 6 +- .../internal/session/sync/job/SyncWorker.kt | 33 ++++++----- .../android/internal/util/CancelableWork.kt | 7 +-- .../internal/worker/WorkManagerUtil.kt | 49 ---------------- 12 files changed, 182 insertions(+), 169 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/WorkManagerProvider.kt delete mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkManagerUtil.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt index dcd84030a7..797581779e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/SasTransportRoomMessage.kt @@ -15,7 +15,6 @@ */ package im.vector.matrix.android.internal.crypto.verification -import android.content.Context import androidx.lifecycle.Observer import androidx.work.* import com.zhuinden.monarchy.Monarchy @@ -29,8 +28,9 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart import im.vector.matrix.android.internal.di.DeviceId import im.vector.matrix.android.internal.di.SessionId import im.vector.matrix.android.internal.di.UserId +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory -import im.vector.matrix.android.internal.worker.WorkManagerUtil +import im.vector.matrix.android.internal.util.StringProvider import im.vector.matrix.android.internal.worker.WorkerParamsFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -41,7 +41,8 @@ import java.util.concurrent.TimeUnit import javax.inject.Inject internal class SasTransportRoomMessage( - private val context: Context, + private val workManagerProvider: WorkManagerProvider, + private val stringProvider: StringProvider, private val sessionId: String, private val userId: String, private val userDeviceId: String?, @@ -88,7 +89,8 @@ internal class SasTransportRoomMessage( // } // }, listenerExecutor) - val workLiveData = WorkManager.getInstance(context).getWorkInfosForUniqueWorkLiveData("${roomId}_VerificationWork") + val workLiveData = workManagerProvider.workManager + .getWorkInfosForUniqueWorkLiveData("${roomId}_VerificationWork") val observer = object : Observer> { override fun onChanged(workInfoList: List?) { @@ -122,7 +124,7 @@ internal class SasTransportRoomMessage( roomId: String, callback: (String?, MessageVerificationRequestContent?) -> Unit) { val info = MessageVerificationRequestContent( - body = context.getString(R.string.key_verification_request_fallback_message, userId), + body = stringProvider.getString(R.string.key_verification_request_fallback_message, userId), fromDevice = userDeviceId ?: "", toUserId = otherUserId, methods = listOf(KeyVerificationStart.VERIF_METHOD_SAS) @@ -141,20 +143,21 @@ internal class SasTransportRoomMessage( event = event )) - val workRequest = WorkManagerUtil.matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .setInputData(workerParams) .setBackoffCriteria(BackoffPolicy.LINEAR, 2_000L, TimeUnit.MILLISECONDS) .build() - WorkManager.getInstance(context) + workManagerProvider.workManager .beginUniqueWork("${roomId}_VerificationWork", ExistingWorkPolicy.APPEND, workRequest) .enqueue() // I cannot just listen to the given work request, because when used in a uniqueWork, // The callback is called while it is still Running ... - val workLiveData = WorkManager.getInstance(context).getWorkInfosForUniqueWorkLiveData("${roomId}_VerificationWork") + val workLiveData = workManagerProvider.workManager + .getWorkInfosForUniqueWorkLiveData("${roomId}_VerificationWork") val observer = object : Observer> { override fun onChanged(workInfoList: List?) { @@ -213,12 +216,12 @@ internal class SasTransportRoomMessage( } private fun enqueueSendWork(workerParams: Data): Pair { - val workRequest = WorkManagerUtil.matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .setInputData(workerParams) .setBackoffCriteria(BackoffPolicy.LINEAR, 2_000L, TimeUnit.MILLISECONDS) .build() - return WorkManager.getInstance(context) + return workManagerProvider.workManager .beginUniqueWork("${roomId}_VerificationWork", ExistingWorkPolicy.APPEND, workRequest) .enqueue() to workRequest.id } @@ -290,7 +293,8 @@ internal class SasTransportRoomMessage( } internal class SasTransportRoomMessageFactory @Inject constructor( - private val context: Context, + private val workManagerProvider: WorkManagerProvider, + private val stringProvider: StringProvider, private val monarchy: Monarchy, @SessionId private val sessionId: String, @@ -301,6 +305,6 @@ internal class SasTransportRoomMessageFactory @Inject constructor( private val localEchoEventFactory: LocalEchoEventFactory) { fun createTransport(roomId: String, tx: SASVerificationTransaction?): SasTransportRoomMessage { - return SasTransportRoomMessage(context, sessionId, userId, deviceId, roomId, monarchy, localEchoEventFactory, tx) + return SasTransportRoomMessage(workManagerProvider, stringProvider, sessionId, userId, deviceId, roomId, monarchy, localEchoEventFactory, tx) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/WorkManagerProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/WorkManagerProvider.kt new file mode 100644 index 0000000000..82091be697 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/WorkManagerProvider.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.android.internal.di + +import android.content.Context +import androidx.work.* +import javax.inject.Inject + +internal class WorkManagerProvider @Inject constructor( + context: Context, + @SessionId private val sessionId: String +) { + private val tag = MATRIX_SDK_TAG_PREFIX + sessionId + + val workManager = WorkManager.getInstance(context) + + /** + * Create a OneTimeWorkRequestBuilder, with the Matrix SDK tag + */ + inline fun matrixOneTimeWorkRequestBuilder() = + OneTimeWorkRequestBuilder() + .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 + */ + fun cancelAllWorks() { + workManager.let { + it.cancelAllWorkByTag(tag) + it.pruneWork() + } + } + + companion object { + private const val MATRIX_SDK_TAG_PREFIX = "MatrixSDK-" + + /** + * Default constraints: connected network + */ + val workConstraints = Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index e22e47bc1c..537bc63355 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -16,7 +16,6 @@ package im.vector.matrix.android.internal.session -import android.content.Context import androidx.annotation.MainThread import androidx.lifecycle.LiveData import dagger.Lazy @@ -46,6 +45,7 @@ import im.vector.matrix.android.internal.auth.SessionParamsStore import im.vector.matrix.android.internal.crypto.DefaultCryptoService import im.vector.matrix.android.internal.database.LiveEntityObserver import im.vector.matrix.android.internal.di.SessionId +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.session.sync.SyncTaskSequencer import im.vector.matrix.android.internal.session.sync.SyncTokenStore import im.vector.matrix.android.internal.session.sync.job.SyncThread @@ -63,7 +63,7 @@ import javax.inject.Provider @SessionScope internal class DefaultSession @Inject constructor( override val sessionParams: SessionParams, - private val context: Context, + private val workManagerProvider: WorkManagerProvider, private val eventBus: EventBus, @SessionId override val sessionId: String, @@ -122,15 +122,15 @@ internal class DefaultSession @Inject constructor( } override fun requireBackgroundSync() { - SyncWorker.requireBackgroundSync(context, sessionId) + SyncWorker.requireBackgroundSync(workManagerProvider, sessionId) } override fun startAutomaticBackgroundSync(repeatDelay: Long) { - SyncWorker.automaticallyBackgroundSync(context, sessionId, 0, repeatDelay) + SyncWorker.automaticallyBackgroundSync(workManagerProvider, sessionId, 0, repeatDelay) } override fun stopAnyBackgroundSync() { - SyncWorker.stopAnyBackgroundSync(context) + SyncWorker.stopAnyBackgroundSync(workManagerProvider) } override fun startSync(fromForeground: Boolean) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt index a60bc78b6c..3ca5a03822 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt @@ -16,9 +16,7 @@ package im.vector.matrix.android.internal.session.group -import android.content.Context import androidx.work.ExistingWorkPolicy -import androidx.work.WorkManager import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.internal.database.RealmLiveEntityObserver @@ -27,8 +25,7 @@ import im.vector.matrix.android.internal.database.model.GroupEntity import im.vector.matrix.android.internal.database.model.GroupSummaryEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.SessionId -import im.vector.matrix.android.internal.worker.WorkManagerUtil -import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.worker.WorkerParamsFactory import io.realm.OrderedCollectionChangeSet import io.realm.RealmResults @@ -38,7 +35,7 @@ import javax.inject.Inject private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER" internal class GroupSummaryUpdater @Inject constructor( - private val context: Context, + private val workManagerProvider: WorkManagerProvider, @SessionId private val sessionId: String, private val monarchy: Monarchy) : RealmLiveEntityObserver(monarchy.realmConfiguration) { @@ -72,12 +69,12 @@ internal class GroupSummaryUpdater @Inject constructor( val workData = WorkerParamsFactory.toData(getGroupDataWorkerParams) - val sendWork = matrixOneTimeWorkRequestBuilder() + val sendWork = workManagerProvider.matrixOneTimeWorkRequestBuilder() .setInputData(workData) - .setConstraints(WorkManagerUtil.workConstraints) + .setConstraints(WorkManagerProvider.workConstraints) .build() - WorkManager.getInstance(context) + workManagerProvider.workManager .beginUniqueWork(GET_GROUP_DATA_WORKER, ExistingWorkPolicy.APPEND, sendWork) .enqueue() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt index cdbf6aeee4..9d80223149 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/pushers/DefaultPusherService.kt @@ -15,10 +15,8 @@ */ package im.vector.matrix.android.internal.session.pushers -import android.content.Context import androidx.lifecycle.LiveData import androidx.work.BackoffPolicy -import androidx.work.WorkManager import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.pushers.Pusher @@ -27,17 +25,16 @@ import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.PusherEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.SessionId +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith -import im.vector.matrix.android.internal.worker.WorkManagerUtil -import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory import java.util.* import java.util.concurrent.TimeUnit import javax.inject.Inject internal class DefaultPusherService @Inject constructor( - private val context: Context, + private val workManagerProvider: WorkManagerProvider, private val monarchy: Monarchy, @SessionId private val sessionId: String, private val getPusherTask: GetPushersTask, @@ -68,12 +65,12 @@ internal class DefaultPusherService @Inject constructor( val params = AddHttpPusherWorker.Params(sessionId, pusher) - val request = matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + val request = workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .setInputData(WorkerParamsFactory.toData(params)) .setBackoffCriteria(BackoffPolicy.LINEAR, 10_000L, TimeUnit.MILLISECONDS) .build() - WorkManager.getInstance(context).enqueue(request) + workManagerProvider.workManager.enqueue(request) return request.id } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt index 1b2b27a3eb..6804ac495f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt @@ -15,7 +15,6 @@ */ package im.vector.matrix.android.internal.session.room.relation -import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import androidx.work.OneTimeWorkRequest @@ -39,6 +38,7 @@ import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryE import im.vector.matrix.android.internal.database.model.TimelineEventEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.SessionId +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.session.room.send.EncryptEventWorker import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory import im.vector.matrix.android.internal.session.room.send.RedactEventWorker @@ -53,8 +53,9 @@ import timber.log.Timber internal class DefaultRelationService @AssistedInject constructor( @Assisted private val roomId: String, - private val context: Context, @SessionId private val sessionId: String, + private val workManagerProvider: WorkManagerProvider, + private val timeLineEveSendEventWorkCommon: TimelineSendEventWorkCommon, private val eventFactory: LocalEchoEventFactory, private val cryptoService: CryptoService, private val findReactionEventForUndoTask: FindReactionEventForUndoTask, @@ -85,8 +86,8 @@ internal class DefaultRelationService @AssistedInject constructor( val event = eventFactory.createReactionEvent(roomId, targetEventId, reaction) .also { saveLocalEcho(it) } val sendRelationWork = createSendEventWork(event, true) - TimelineSendEventWorkCommon.postWork(context, roomId, sendRelationWork) - CancelableWork(context, sendRelationWork.id) + timeLineEveSendEventWorkCommon.postWork(roomId, sendRelationWork) + CancelableWork(workManagerProvider.workManager, sendRelationWork.id) } else { Timber.w("Reaction already added") NoOpCancellable @@ -111,7 +112,7 @@ internal class DefaultRelationService @AssistedInject constructor( .also { saveLocalEcho(it) } val redactWork = createRedactEventWork(redactEvent, toRedact, null) - TimelineSendEventWorkCommon.postWork(context, roomId, redactWork) + timeLineEveSendEventWorkCommon.postWork(roomId, redactWork) } } } @@ -132,7 +133,7 @@ internal class DefaultRelationService @AssistedInject constructor( eventId, reason) val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - return TimelineSendEventWorkCommon.createWork(redactWorkData, true) + return timeLineEveSendEventWorkCommon.createWork(redactWorkData, true) } override fun editTextMessage(targetEventId: String, @@ -146,12 +147,12 @@ internal class DefaultRelationService @AssistedInject constructor( return if (cryptoService.isRoomEncrypted(roomId)) { val encryptWork = createEncryptEventWork(event, listOf("m.relates_to")) val workRequest = createSendEventWork(event, false) - TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest) - CancelableWork(context, encryptWork.id) + timeLineEveSendEventWorkCommon.postSequentialWorks(roomId, encryptWork, workRequest) + CancelableWork(workManagerProvider.workManager, encryptWork.id) } else { val workRequest = createSendEventWork(event, true) - TimelineSendEventWorkCommon.postWork(context, roomId, workRequest) - CancelableWork(context, workRequest.id) + timeLineEveSendEventWorkCommon.postWork(roomId, workRequest) + CancelableWork(workManagerProvider.workManager, workRequest.id) } } @@ -168,12 +169,12 @@ internal class DefaultRelationService @AssistedInject constructor( return if (cryptoService.isRoomEncrypted(roomId)) { val encryptWork = createEncryptEventWork(event, listOf("m.relates_to")) val workRequest = createSendEventWork(event, false) - TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest) - CancelableWork(context, encryptWork.id) + timeLineEveSendEventWorkCommon.postSequentialWorks(roomId, encryptWork, workRequest) + CancelableWork(workManagerProvider.workManager, encryptWork.id) } else { val workRequest = createSendEventWork(event, true) - TimelineSendEventWorkCommon.postWork(context, roomId, workRequest) - CancelableWork(context, workRequest.id) + timeLineEveSendEventWorkCommon.postWork(roomId, workRequest) + CancelableWork(workManagerProvider.workManager, workRequest.id) } } @@ -194,12 +195,12 @@ internal class DefaultRelationService @AssistedInject constructor( return if (cryptoService.isRoomEncrypted(roomId)) { val encryptWork = createEncryptEventWork(event, listOf("m.relates_to")) val workRequest = createSendEventWork(event, false) - TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, workRequest) - CancelableWork(context, encryptWork.id) + timeLineEveSendEventWorkCommon.postSequentialWorks(roomId, encryptWork, workRequest) + CancelableWork(workManagerProvider.workManager, encryptWork.id) } else { val workRequest = createSendEventWork(event, true) - TimelineSendEventWorkCommon.postWork(context, roomId, workRequest) - CancelableWork(context, workRequest.id) + timeLineEveSendEventWorkCommon.postWork(roomId, workRequest) + CancelableWork(workManagerProvider.workManager, workRequest.id) } } @@ -207,13 +208,13 @@ internal class DefaultRelationService @AssistedInject constructor( // Same parameter val params = EncryptEventWorker.Params(sessionId, roomId, event, keepKeys) val sendWorkData = WorkerParamsFactory.toData(params) - return TimelineSendEventWorkCommon.createWork(sendWorkData, true) + return timeLineEveSendEventWorkCommon.createWork(sendWorkData, true) } private fun createSendEventWork(event: Event, startChain: Boolean): OneTimeWorkRequest { val sendContentWorkerParams = SendEventWorker.Params(sessionId, roomId, event) val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - return TimelineSendEventWorkCommon.createWork(sendWorkData, startChain) + return timeLineEveSendEventWorkCommon.createWork(sendWorkData, startChain) } override fun getEventAnnotationsSummary(eventId: String): EventAnnotationsSummary? { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt index 9942e36593..fa86e43e36 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/DefaultSendService.kt @@ -16,7 +16,6 @@ package im.vector.matrix.android.internal.session.room.send -import android.content.Context import androidx.work.* import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject @@ -38,12 +37,11 @@ import im.vector.matrix.android.internal.database.model.TimelineEventEntity import im.vector.matrix.android.internal.database.query.findAllInRoomWithSendStates import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.SessionId +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.session.content.UploadContentWorker import im.vector.matrix.android.internal.session.room.timeline.TimelineSendEventWorkCommon import im.vector.matrix.android.internal.util.CancelableWork import im.vector.matrix.android.internal.worker.AlwaysSuccessfulWorker -import im.vector.matrix.android.internal.worker.WorkManagerUtil -import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory import im.vector.matrix.android.internal.worker.startChain import timber.log.Timber @@ -55,7 +53,8 @@ private const val BACKOFF_DELAY = 10_000L internal class DefaultSendService @AssistedInject constructor( @Assisted private val roomId: String, - private val context: Context, + private val workManagerProvider: WorkManagerProvider, + private val timelineSendEventWorkCommon: TimelineSendEventWorkCommon, @SessionId private val sessionId: String, private val localEchoEventFactory: LocalEchoEventFactory, private val cryptoService: CryptoService, @@ -91,12 +90,12 @@ internal class DefaultSendService @AssistedInject constructor( Timber.v("Send event in encrypted room") val encryptWork = createEncryptEventWork(event, true) val sendWork = createSendEventWork(event, false) - TimelineSendEventWorkCommon.postSequentialWorks(context, roomId, encryptWork, sendWork) - CancelableWork(context, encryptWork.id) + timelineSendEventWorkCommon.postSequentialWorks(roomId, encryptWork, sendWork) + CancelableWork(workManagerProvider.workManager, encryptWork.id) } else { val sendWork = createSendEventWork(event, true) - TimelineSendEventWorkCommon.postWork(context, roomId, sendWork) - CancelableWork(context, sendWork.id) + timelineSendEventWorkCommon.postWork(roomId, sendWork) + CancelableWork(workManagerProvider.workManager, sendWork.id) } } @@ -109,8 +108,8 @@ internal class DefaultSendService @AssistedInject constructor( override fun redactEvent(event: Event, reason: String?): Cancelable { // TODO manage media/attachements? val redactWork = createRedactEventWork(event, reason) - TimelineSendEventWorkCommon.postWork(context, roomId, redactWork) - return CancelableWork(context, redactWork.id) + timelineSendEventWorkCommon.postWork(roomId, redactWork) + return CancelableWork(workManagerProvider.workManager, redactWork.id) } override fun resendTextMessage(localEcho: TimelineEvent): Cancelable? { @@ -168,16 +167,16 @@ internal class DefaultSendService @AssistedInject constructor( } override fun clearSendingQueue() { - TimelineSendEventWorkCommon.cancelAllWorks(context, roomId) - WorkManager.getInstance(context).cancelUniqueWork(buildWorkName(UPLOAD_WORK)) + timelineSendEventWorkCommon.cancelAllWorks(roomId) + workManagerProvider.workManager.cancelUniqueWork(buildWorkName(UPLOAD_WORK)) // Replace the worker chains with a AlwaysSuccessfulWorker, to ensure the queues are well emptied - matrixOneTimeWorkRequestBuilder() + workManagerProvider.matrixOneTimeWorkRequestBuilder() .build().let { - TimelineSendEventWorkCommon.postWork(context, roomId, it, ExistingWorkPolicy.REPLACE) + timelineSendEventWorkCommon.postWork(roomId, it, ExistingWorkPolicy.REPLACE) // need to clear also image sending queue - WorkManager.getInstance(context) + workManagerProvider.workManager .beginUniqueWork(buildWorkName(UPLOAD_WORK), ExistingWorkPolicy.REPLACE, it) .enqueue() } @@ -254,7 +253,7 @@ internal class DefaultSendService @AssistedInject constructor( if (isRoomEncrypted) { val encryptWork = createEncryptEventWork(localEcho, false /*not start of chain, take input error*/) - val op: Operation = WorkManager.getInstance(context) + val op: Operation = workManagerProvider.workManager .beginUniqueWork(buildWorkName(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork) .then(encryptWork) .then(sendWork) @@ -267,13 +266,13 @@ internal class DefaultSendService @AssistedInject constructor( } }, workerFutureListenerExecutor) } else { - WorkManager.getInstance(context) + workManagerProvider.workManager .beginUniqueWork(buildWorkName(UPLOAD_WORK), ExistingWorkPolicy.APPEND, uploadWork) .then(sendWork) .enqueue() } - return CancelableWork(context, sendWork.id) + return CancelableWork(workManagerProvider.workManager, sendWork.id) } private fun saveLocalEcho(event: Event) { @@ -289,8 +288,8 @@ internal class DefaultSendService @AssistedInject constructor( val params = EncryptEventWorker.Params(sessionId, roomId, event) val sendWorkData = WorkerParamsFactory.toData(params) - return matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + return workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .setInputData(sendWorkData) .startChain(startChain) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) @@ -301,7 +300,7 @@ internal class DefaultSendService @AssistedInject constructor( val sendContentWorkerParams = SendEventWorker.Params(sessionId, roomId, event) val sendWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - return TimelineSendEventWorkCommon.createWork(sendWorkData, startChain) + return timelineSendEventWorkCommon.createWork(sendWorkData, startChain) } private fun createRedactEventWork(event: Event, reason: String?): OneTimeWorkRequest { @@ -310,7 +309,7 @@ internal class DefaultSendService @AssistedInject constructor( } val sendContentWorkerParams = RedactEventWorker.Params(sessionId, redactEvent.eventId!!, roomId, event.eventId, reason) val redactWorkData = WorkerParamsFactory.toData(sendContentWorkerParams) - return TimelineSendEventWorkCommon.createWork(redactWorkData, true) + return timelineSendEventWorkCommon.createWork(redactWorkData, true) } private fun createUploadMediaWork(event: Event, @@ -320,8 +319,8 @@ internal class DefaultSendService @AssistedInject constructor( val uploadMediaWorkerParams = UploadContentWorker.Params(sessionId, roomId, event, attachment, isRoomEncrypted) val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams) - return matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + return workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .startChain(startChain) .setInputData(uploadWorkData) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt index f6f894d860..b042aa4e06 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineSendEventWorkCommon.kt @@ -15,32 +15,30 @@ */ package im.vector.matrix.android.internal.session.room.timeline -import android.content.Context import androidx.work.* -import im.vector.matrix.android.internal.worker.WorkManagerUtil -import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.worker.startChain import java.util.concurrent.TimeUnit - -private const val SEND_WORK = "SEND_WORK" -private const val BACKOFF_DELAY = 10_000L +import javax.inject.Inject /** * Helper class for sending event related works. * All send event from a room are using the same workchain, in order to ensure order. - * WorkRequest must always return success (even if server error, in this case marking the event as failed to send) - * , if not the chain will be doomed in failed state. - * + * WorkRequest must always return success (even if server error, in this case marking the event as failed to send), + * if not the chain will be doomed in failed state. */ -internal object TimelineSendEventWorkCommon { +internal class TimelineSendEventWorkCommon @Inject constructor( + // TODO @Assisted private val roomId: String, + private val workManagerProvider: WorkManagerProvider +) { - fun postSequentialWorks(context: Context, roomId: String, vararg workRequests: OneTimeWorkRequest) { + fun postSequentialWorks(roomId: String, vararg workRequests: OneTimeWorkRequest) { when { workRequests.isEmpty() -> return - workRequests.size == 1 -> postWork(context, roomId, workRequests.first()) + workRequests.size == 1 -> postWork(roomId, workRequests.first()) else -> { val firstWork = workRequests.first() - var continuation = WorkManager.getInstance(context) + var continuation = workManagerProvider.workManager .beginUniqueWork(buildWorkName(roomId), ExistingWorkPolicy.APPEND, firstWork) for (i in 1 until workRequests.size) { val workRequest = workRequests[i] @@ -51,15 +49,15 @@ internal object TimelineSendEventWorkCommon { } } - fun postWork(context: Context, roomId: String, workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND) { - WorkManager.getInstance(context) + fun postWork(roomId: String, workRequest: OneTimeWorkRequest, policy: ExistingWorkPolicy = ExistingWorkPolicy.APPEND) { + workManagerProvider.workManager .beginUniqueWork(buildWorkName(roomId), policy, workRequest) .enqueue() } inline fun createWork(data: Data, startChain: Boolean): OneTimeWorkRequest { - return matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + return workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .startChain(startChain) .setInputData(data) .setBackoffCriteria(BackoffPolicy.LINEAR, BACKOFF_DELAY, TimeUnit.MILLISECONDS) @@ -70,7 +68,13 @@ internal object TimelineSendEventWorkCommon { return "${roomId}_$SEND_WORK" } - fun cancelAllWorks(context: Context, roomId: String) { - WorkManager.getInstance(context).cancelUniqueWork(buildWorkName(roomId)) + fun cancelAllWorks(roomId: String) { + workManagerProvider.workManager + .cancelUniqueWork(buildWorkName(roomId)) + } + + companion object { + private const val SEND_WORK = "SEND_WORK" + private const val BACKOFF_DELAY = 10_000L } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt index e6913f8b54..05a2324047 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/signout/SignOutTask.kt @@ -16,7 +16,6 @@ package im.vector.matrix.android.internal.session.signout -import android.content.Context import im.vector.matrix.android.BuildConfig import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.failure.MatrixError @@ -29,7 +28,6 @@ import im.vector.matrix.android.internal.network.executeRequest import im.vector.matrix.android.internal.session.SessionModule import im.vector.matrix.android.internal.session.cache.ClearCacheTask import im.vector.matrix.android.internal.task.Task -import im.vector.matrix.android.internal.worker.WorkManagerUtil import io.realm.Realm import io.realm.RealmConfiguration import org.greenrobot.eventbus.EventBus @@ -45,7 +43,7 @@ internal interface SignOutTask : Task { } internal class DefaultSignOutTask @Inject constructor( - private val context: Context, + private val workManagerProvider: WorkManagerProvider, @SessionId private val sessionId: String, private val signOutAPI: SignOutAPI, private val sessionManager: SessionManager, @@ -87,7 +85,7 @@ internal class DefaultSignOutTask @Inject constructor( sessionManager.releaseSession(sessionId) Timber.d("SignOut: cancel pending works...") - WorkManagerUtil.cancelAllWorks(context) + workManagerProvider.cancelAllWorks() Timber.d("SignOut: delete session params...") sessionParamsStore.delete(sessionId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt index 3637cc624f..c844db8d33 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/job/SyncWorker.kt @@ -16,15 +16,17 @@ package im.vector.matrix.android.internal.session.sync.job import android.content.Context -import androidx.work.* +import androidx.work.BackoffPolicy +import androidx.work.CoroutineWorker +import androidx.work.ExistingWorkPolicy +import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass import im.vector.matrix.android.api.failure.isTokenError +import im.vector.matrix.android.internal.di.WorkManagerProvider import im.vector.matrix.android.internal.network.NetworkConnectivityChecker import im.vector.matrix.android.internal.session.sync.SyncTask import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.worker.SessionWorkerParams -import im.vector.matrix.android.internal.worker.WorkManagerUtil -import im.vector.matrix.android.internal.worker.WorkManagerUtil.matrixOneTimeWorkRequestBuilder import im.vector.matrix.android.internal.worker.WorkerParamsFactory import im.vector.matrix.android.internal.worker.getSessionComponent import timber.log.Timber @@ -75,30 +77,33 @@ internal class SyncWorker(context: Context, companion object { - const val BG_SYNC_WORK_NAME = "BG_SYNCP" + private const val BG_SYNC_WORK_NAME = "BG_SYNCP" - fun requireBackgroundSync(context: Context, sessionId: String, serverTimeout: Long = 0) { + fun requireBackgroundSync(workManagerProvider: WorkManagerProvider, sessionId: String, serverTimeout: Long = 0) { val data = WorkerParamsFactory.toData(Params(sessionId, serverTimeout, false)) - val workRequest = matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .setBackoffCriteria(BackoffPolicy.LINEAR, 1_000, TimeUnit.MILLISECONDS) .setInputData(data) .build() - WorkManager.getInstance(context).enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest) + workManagerProvider.workManager + .enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest) } - fun automaticallyBackgroundSync(context: Context, sessionId: String, serverTimeout: Long = 0, delay: Long = 30_000) { + fun automaticallyBackgroundSync(workManagerProvider: WorkManagerProvider, sessionId: String, serverTimeout: Long = 0, delay: Long = 30_000) { val data = WorkerParamsFactory.toData(Params(sessionId, serverTimeout, true)) - val workRequest = matrixOneTimeWorkRequestBuilder() - .setConstraints(WorkManagerUtil.workConstraints) + val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setConstraints(WorkManagerProvider.workConstraints) .setInputData(data) .setBackoffCriteria(BackoffPolicy.LINEAR, delay, TimeUnit.MILLISECONDS) .build() - WorkManager.getInstance(context).enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest) + workManagerProvider.workManager + .enqueueUniqueWork(BG_SYNC_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest) } - fun stopAnyBackgroundSync(context: Context) { - WorkManager.getInstance(context).cancelUniqueWork(BG_SYNC_WORK_NAME) + fun stopAnyBackgroundSync(workManagerProvider: WorkManagerProvider) { + workManagerProvider.workManager + .cancelUniqueWork(BG_SYNC_WORK_NAME) } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt index bff20a80e7..cba104ebe8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/CancelableWork.kt @@ -16,15 +16,14 @@ package im.vector.matrix.android.internal.util -import android.content.Context import androidx.work.WorkManager import im.vector.matrix.android.api.util.Cancelable -import java.util.UUID +import java.util.* -internal class CancelableWork(private val context: Context, +internal class CancelableWork(private val workManager: WorkManager, private val workId: UUID) : Cancelable { override fun cancel() { - WorkManager.getInstance(context).cancelWorkById(workId) + workManager.cancelWorkById(workId) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkManagerUtil.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkManagerUtil.kt deleted file mode 100644 index 27ec28dcac..0000000000 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/worker/WorkManagerUtil.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package im.vector.matrix.android.internal.worker - -import android.content.Context -import androidx.work.* - -// TODO Multiaccount -internal object WorkManagerUtil { - private const val MATRIX_SDK_TAG = "MatrixSDK" - - /** - * Default constraints: connected network - */ - val workConstraints = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - - /** - * Create a OneTimeWorkRequestBuilder, with the Matrix SDK tag - */ - inline fun matrixOneTimeWorkRequestBuilder() = - OneTimeWorkRequestBuilder() - .addTag(MATRIX_SDK_TAG) - - /** - * Cancel all works instantiated by the Matrix SDK and not those from the SDK client - */ - fun cancelAllWorks(context: Context) { - WorkManager.getInstance(context).also { - it.cancelAllWorkByTag(MATRIX_SDK_TAG) - it.pruneWork() - } - } -}