diff --git a/sentinel/src/main/AndroidManifest.xml b/sentinel/src/main/AndroidManifest.xml index 394f16e2..61a51446 100644 --- a/sentinel/src/main/AndroidManifest.xml +++ b/sentinel/src/main/AndroidManifest.xml @@ -13,10 +13,10 @@ android:name=".ui.main.SentinelActivity" android:exported="true" android:label="@string/sentinel_name" + android:permission="com.infinum.sentinel.permission.ACCESS_SENTINEL" android:taskAffinity="com.infinum.sentinel" - android:theme="@style/Sentinel.Theme" - android:permission="com.infinum.sentinel.permission.ACCESS_SENTINEL"> - + @@ -119,17 +119,6 @@ android:value="androidx.startup" /> - - - - diff --git a/sentinel/src/main/kotlin/com/infinum/sentinel/di/LibraryComponents.kt b/sentinel/src/main/kotlin/com/infinum/sentinel/di/LibraryComponents.kt index 72d71cb2..68800d7f 100644 --- a/sentinel/src/main/kotlin/com/infinum/sentinel/di/LibraryComponents.kt +++ b/sentinel/src/main/kotlin/com/infinum/sentinel/di/LibraryComponents.kt @@ -42,6 +42,7 @@ internal object LibraryComponents { tools.filterIsInstance().firstOrNull()?.userCertificates.orEmpty(), onTriggered ) + WorkManagerInitializer.init(domainComponent) domainComponent.setup() } diff --git a/sentinel/src/main/kotlin/com/infinum/sentinel/di/WorkManagerInitializer.kt b/sentinel/src/main/kotlin/com/infinum/sentinel/di/WorkManagerInitializer.kt new file mode 100644 index 00000000..49f278c9 --- /dev/null +++ b/sentinel/src/main/kotlin/com/infinum/sentinel/di/WorkManagerInitializer.kt @@ -0,0 +1,14 @@ +package com.infinum.sentinel.di + +import com.infinum.sentinel.di.component.DomainComponent +import com.infinum.sentinel.ui.certificates.observer.CertificateCheckWorker +import com.infinum.sentinel.ui.certificates.observer.DelegateWorker +import com.infinum.sentinel.ui.certificates.observer.SentinelWorkerFactory + +internal object WorkManagerInitializer { + + fun init(domainComponent: DomainComponent) { + DelegateWorker.workerFactories[CertificateCheckWorker.NAME] = + SentinelWorkerFactory(domainComponent.collectors, domainComponent.notificationFactory) + } +} diff --git a/sentinel/src/main/kotlin/com/infinum/sentinel/di/component/DomainComponent.kt b/sentinel/src/main/kotlin/com/infinum/sentinel/di/component/DomainComponent.kt index 2301caeb..f9945494 100644 --- a/sentinel/src/main/kotlin/com/infinum/sentinel/di/component/DomainComponent.kt +++ b/sentinel/src/main/kotlin/com/infinum/sentinel/di/component/DomainComponent.kt @@ -50,7 +50,6 @@ import com.infinum.sentinel.ui.bundles.callbacks.BundleMonitorNotificationCallba import com.infinum.sentinel.ui.bundles.details.BundleDetailsActivity import com.infinum.sentinel.ui.certificates.observer.CertificatesObserver import com.infinum.sentinel.ui.certificates.observer.SentinelWorkManager -import com.infinum.sentinel.ui.certificates.observer.SentinelWorkerFactory import com.infinum.sentinel.ui.crash.anr.SentinelAnrObserver import com.infinum.sentinel.ui.crash.anr.SentinelAnrObserverRunnable import com.infinum.sentinel.ui.crash.anr.SentinelUiAnrObserver @@ -91,8 +90,6 @@ internal abstract class DomainComponent( abstract val sentinelAnrObserver: SentinelAnrObserver - abstract val sentinelWorkerFactory: SentinelWorkerFactory - abstract val sentinelWorkManager: SentinelWorkManager abstract val sentinelAnrObserverRunnable: SentinelAnrObserverRunnable @@ -157,15 +154,10 @@ internal abstract class DomainComponent( fun sentinelAnrObserverRunnable(dao: CrashesDao): SentinelAnrObserverRunnable = SentinelAnrObserverRunnable(context, notificationFactory, dao) - @Provides - @DomainScope - fun sentinelWorkerFactory(): SentinelWorkerFactory = - SentinelWorkerFactory(collectors, notificationFactory) - @Provides @DomainScope fun sentinelWorkManager(): SentinelWorkManager = - SentinelWorkManager(context, sentinelWorkerFactory) + SentinelWorkManager(context) @Provides @DomainScope diff --git a/sentinel/src/main/kotlin/com/infinum/sentinel/ui/certificates/observer/DelegateWorker.kt b/sentinel/src/main/kotlin/com/infinum/sentinel/ui/certificates/observer/DelegateWorker.kt new file mode 100644 index 00000000..318599d2 --- /dev/null +++ b/sentinel/src/main/kotlin/com/infinum/sentinel/ui/certificates/observer/DelegateWorker.kt @@ -0,0 +1,54 @@ +package com.infinum.sentinel.ui.certificates.observer + +import android.content.Context +import androidx.annotation.UiThread +import androidx.work.ListenableWorker +import androidx.work.WorkerFactory +import androidx.work.WorkerParameters +import com.google.common.util.concurrent.ListenableFuture +import com.infinum.sentinel.ui.shared.Constants.Keys.WORKER_CLASS_NAME +import com.infinum.sentinel.ui.shared.Constants.Keys.WORKER_ID + +/** + * A worker to delegate work requests from within the library to workers + * that require factories with custom dependencies. + */ +internal class DelegateWorker( + appContext: Context, + parameters: WorkerParameters, +) : ListenableWorker(appContext, parameters) { + + private val workerClassName = + parameters.inputData.getString(WORKER_CLASS_NAME) ?: "" + private val workerId = parameters.inputData.getString(WORKER_ID) + private val delegateWorkerFactory = workerFactories[workerId] + private val delegatedWorker = delegateWorkerFactory?.createWorker(appContext, workerClassName, parameters) + + override fun startWork(): ListenableFuture { + return if (delegatedWorker != null) { + delegatedWorker.startWork() + } else { + val errorMessage = "No delegateWorker available for $workerId" + + " with workerClassName of $workerClassName. Is the " + + "DelegateWorker.workerFactories populated correctly?" + throw IllegalStateException(errorMessage) + } + } + + companion object { + const val DELEGATE_WORKER_ID = "com.infinum.sentinel.ui.certificates.observer.CertificateCheckWorker" + + val workerFactories = object : AbstractMutableMap() { + + private val backingWorkerMap = mutableMapOf() + + @UiThread + override fun put(key: String, value: WorkerFactory): WorkerFactory? { + return backingWorkerMap.put(key, value) + } + + override val entries: MutableSet> + get() = backingWorkerMap.entries + } + } +} diff --git a/sentinel/src/main/kotlin/com/infinum/sentinel/ui/certificates/observer/SentinelWorkManager.kt b/sentinel/src/main/kotlin/com/infinum/sentinel/ui/certificates/observer/SentinelWorkManager.kt index 944d7b33..6d3103e8 100644 --- a/sentinel/src/main/kotlin/com/infinum/sentinel/ui/certificates/observer/SentinelWorkManager.kt +++ b/sentinel/src/main/kotlin/com/infinum/sentinel/ui/certificates/observer/SentinelWorkManager.kt @@ -4,14 +4,12 @@ import android.content.Context import android.os.Build import androidx.annotation.RequiresApi import androidx.lifecycle.asFlow -import androidx.work.Configuration import androidx.work.Constraints import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.NetworkType import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkInfo import androidx.work.WorkManager -import androidx.work.WorkerFactory import androidx.work.workDataOf import com.infinum.sentinel.BuildConfig import com.infinum.sentinel.data.models.local.CertificateMonitorEntity @@ -19,6 +17,8 @@ import com.infinum.sentinel.ui.shared.Constants.Keys.EXPIRE_IN_AMOUNT import com.infinum.sentinel.ui.shared.Constants.Keys.EXPIRE_IN_UNIT import com.infinum.sentinel.ui.shared.Constants.Keys.NOTIFY_INVALID_NOW import com.infinum.sentinel.ui.shared.Constants.Keys.NOTIFY_TO_EXPIRE +import com.infinum.sentinel.ui.shared.Constants.Keys.WORKER_CLASS_NAME +import com.infinum.sentinel.ui.shared.Constants.Keys.WORKER_ID import java.time.Duration import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf @@ -28,7 +28,6 @@ import me.tatarka.inject.annotations.Inject @Inject internal class SentinelWorkManager( private val context: Context, - private val workerFactory: WorkerFactory ) { companion object { @@ -36,36 +35,27 @@ internal class SentinelWorkManager( private const val RELEASE_INTERVAL = 1440L } - init { - WorkManager.initialize( - context, - Configuration.Builder() - .setMinimumLoggingLevel(android.util.Log.INFO) - .setWorkerFactory(workerFactory) - .build() - ) - } - @RequiresApi(Build.VERSION_CODES.O) - fun startCertificatesCheck(entity: CertificateMonitorEntity) = + fun startCertificatesCheck(entity: CertificateMonitorEntity) { + + val delegatedWorkData = workDataOf( + WORKER_CLASS_NAME to CertificateCheckWorker::class.qualifiedName, + WORKER_ID to CertificateCheckWorker.NAME, + NOTIFY_INVALID_NOW to entity.notifyInvalidNow, + NOTIFY_TO_EXPIRE to entity.notifyToExpire, + EXPIRE_IN_AMOUNT to entity.expireInAmount, + EXPIRE_IN_UNIT to entity.expireInUnit.name + ) WorkManager.getInstance(context) .enqueueUniquePeriodicWork( - CertificateCheckWorker.NAME, + DelegateWorker.DELEGATE_WORKER_ID, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, - PeriodicWorkRequestBuilder( + PeriodicWorkRequestBuilder( when (BuildConfig.DEBUG) { true -> Duration.ofMinutes(DEBUG_INTERVAL) false -> Duration.ofMinutes(RELEASE_INTERVAL) } - ) - .setInputData( - workDataOf( - NOTIFY_INVALID_NOW to entity.notifyInvalidNow, - NOTIFY_TO_EXPIRE to entity.notifyToExpire, - EXPIRE_IN_AMOUNT to entity.expireInAmount, - EXPIRE_IN_UNIT to entity.expireInUnit.name - ) - ) + ).setInputData(delegatedWorkData) .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.NOT_REQUIRED) @@ -80,6 +70,7 @@ internal class SentinelWorkManager( ) .build() ) + } fun certificatesCheckState(): Flow = WorkManager.getInstance(context) diff --git a/sentinel/src/main/kotlin/com/infinum/sentinel/ui/shared/Constants.kt b/sentinel/src/main/kotlin/com/infinum/sentinel/ui/shared/Constants.kt index 3e4004f9..5ae33f09 100644 --- a/sentinel/src/main/kotlin/com/infinum/sentinel/ui/shared/Constants.kt +++ b/sentinel/src/main/kotlin/com/infinum/sentinel/ui/shared/Constants.kt @@ -14,5 +14,7 @@ internal object Constants { const val NOTIFY_TO_EXPIRE: String = "KEY_NOTIFY_TO_EXPIRE" const val EXPIRE_IN_AMOUNT: String = "KEY_EXPIRE_IN_AMOUNT" const val EXPIRE_IN_UNIT: String = "KEY_EXPIRE_IN_UNIT" + const val WORKER_CLASS_NAME = "WORKER_CLASS_NAME" + const val WORKER_ID = "WORKER_ID" } }