Skip to content
Permalink
Browse files Browse the repository at this point in the history
*Added exponential interval for fake request
  • Loading branch information
Oscar Rodriguez committed Oct 8, 2020
1 parent c158e12 commit 5325277
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 12 deletions.
6 changes: 5 additions & 1 deletion app/src/main/java/es/gob/radarcovid/RadarCovidApplication.kt
Expand Up @@ -14,6 +14,7 @@ import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication
import es.gob.radarcovid.common.base.broadcast.ExposureStatusChangeBroadcastReceiver
import es.gob.radarcovid.common.di.component.DaggerApplicationComponent
import es.gob.radarcovid.datamanager.repository.PreferencesRepository
import es.gob.radarcovid.features.worker.FakeInfectionReportWorker
import io.reactivex.rxjava3.plugins.RxJavaPlugins
import okhttp3.CertificatePinner
Expand All @@ -29,6 +30,9 @@ class RadarCovidApplication : DaggerApplication() {
@Inject
lateinit var certificatePinner: CertificatePinner

@Inject
lateinit var preferencesRepository: PreferencesRepository

@Inject
@Named("userAgent")
lateinit var userAgent: String
Expand All @@ -47,7 +51,7 @@ class RadarCovidApplication : DaggerApplication() {
DP3T.setCertificatePinner(certificatePinner)
DP3T.setUserAgent(userAgent)

FakeInfectionReportWorker.start(this)
FakeInfectionReportWorker.start(this, preferencesRepository)

registerReceiver(ExposureStatusChangeBroadcastReceiver(), DP3T.getUpdateIntentFilter())

Expand Down
Expand Up @@ -57,4 +57,8 @@ interface PreferencesRepository {

fun getHealingTime(): HealingTime

fun getTDummy(): Long

fun setTDummy(time: Long)

}
Expand Up @@ -36,6 +36,7 @@ class PreferencesRepositoryImpl @Inject constructor(@Named("applicationContext")
private const val KEY_REGIONS = "key_regions"
private const val KEY_LANGUAGES = "key_languages"
private const val KEY_HEALING_TIME = "key_healing_time"
private const val KEY_T_DUMMY = "KEY_T_DUMMY"
}

private val preferences = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
Expand Down Expand Up @@ -167,4 +168,12 @@ class PreferencesRepositoryImpl @Inject constructor(@Named("applicationContext")
return Gson().fromJson(healingTimeJson, HealingTime::class.java)
}

override fun getTDummy(): Long {
return preferences.getLong(KEY_T_DUMMY, -1)
}

override fun setTDummy(time: Long) {
preferences.edit().putLong(KEY_T_DUMMY, time).apply()
}

}
Expand Up @@ -13,12 +13,21 @@ package es.gob.radarcovid.features.worker
import android.content.Context
import androidx.work.*
import dagger.android.HasAndroidInjector
import es.gob.radarcovid.datamanager.repository.PreferencesRepository
import es.gob.radarcovid.datamanager.usecase.ReportFakeInfectionUseCase
import org.dpppt.android.sdk.BuildConfig
import org.dpppt.android.sdk.DP3T
import java.security.SecureRandom
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.random.Random


private const val FACTOR_HOUR_MILLIS = 60 * 60 * 1000L
private const val FACTOR_DAY_MILLIS: Long = 24 * FACTOR_HOUR_MILLIS
private const val MAX_DELAY_HOURS: Long = 48
private val SAMPLING_RATE =
if (BuildConfig.DEBUG) 1.0f else 0.2f
private const val KEY_T_DUMMY = "KEY_T_DUMMY"

class FakeInfectionReportWorker(context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
Expand All @@ -31,43 +40,93 @@ class FakeInfectionReportWorker(context: Context, workerParams: WorkerParameters

companion object {

private var clock: Clock = ClockImpl()

private const val TAG = "FakeInfectionReportWorker"

fun start(context: Context) {
start(context, getRandomDelay(), ExistingWorkPolicy.KEEP)
fun start(context: Context, preferencesRepository: PreferencesRepository) {
var tDummy: Long = preferencesRepository.getTDummy()
if (tDummy == -1L) {
tDummy = clock.currentTimeMillis() + clock.syncInterval()
preferencesRepository.setTDummy(tDummy)
}
start(context, tDummy, ExistingWorkPolicy.KEEP)
}

private fun start(
context: Context,
delayInMinutes: Long,
tDummy: Long,
existingWorkPolicy: ExistingWorkPolicy
) {

val now = clock.currentTimeMillis()
val executionDelay = 0L.coerceAtLeast(tDummy - now)
val executionDelayDays =
executionDelay / FACTOR_DAY_MILLIS

val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val work =
OneTimeWorkRequest
.Builder(FakeInfectionReportWorker::class.java)
.setInitialDelay(delayInMinutes, TimeUnit.MINUTES)
.setInitialDelay(executionDelayDays, TimeUnit.MINUTES)
.setConstraints(constraints)
.setInputData(Data.Builder().putLong(KEY_T_DUMMY, tDummy).build())
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(TAG, existingWorkPolicy, work)
}

private fun getRandomDelay(): Long = Random.nextLong(180, 360)
//private fun getRandomDelay(): Long = Random.nextLong(180, 360)

}

@Inject
lateinit var reportFakeInfectionUseCase: ReportFakeInfectionUseCase

@Inject
lateinit var preferencesRepository: PreferencesRepository

override fun doWork(): Result {
if (BuildConfig.DEBUG)
DP3T.addWorkerStartedToHistory(applicationContext, TAG)
reportFakeInfectionUseCase.reportFakeInfection().subscribe()
start(applicationContext, getRandomDelay(), ExistingWorkPolicy.APPEND)
val now = clock.currentTimeMillis()
var tDummy = inputData.getLong(KEY_T_DUMMY, now)
while (tDummy < now) {
if (tDummy >= now - FACTOR_HOUR_MILLIS * MAX_DELAY_HOURS) {
if (BuildConfig.DEBUG)
DP3T.addWorkerStartedToHistory(applicationContext, TAG)
reportFakeInfectionUseCase.reportFakeInfection().subscribe()
}
tDummy += clock.syncInterval();
preferencesRepository.setTDummy(tDummy)
}

start(applicationContext, tDummy, ExistingWorkPolicy.APPEND)
return Result.success()
}


interface Clock {
fun syncInterval(): Long
fun currentTimeMillis(): Long
}

class ClockImpl : Clock {
override fun syncInterval(): Long {
val newDelayDays: Double =
ExponentialDistribution.sampleFromStandard() / SAMPLING_RATE
return (newDelayDays * FACTOR_DAY_MILLIS) as Long
}

override fun currentTimeMillis(): Long {
return System.currentTimeMillis()
}
}

object ExponentialDistribution {
fun sampleFromStandard(): Double {
val random = SecureRandom()
return -Math.log(1.0 - random.nextDouble())
}
}

}

0 comments on commit 5325277

Please sign in to comment.