From 95e68cbbe748f81af1113753c5b99929e3db9ea2 Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Wed, 11 Oct 2023 16:36:02 +0000 Subject: epic18: Trackers control on standalone app (without Ipscrambling). --- trackers/src/main/AndroidManifest.xml | 17 --- .../e/advancedprivacy/trackers/KoinModule.kt | 18 ++- .../trackers/data/RemoteTrackersListRepository.kt | 2 +- .../advancedprivacy/trackers/data/StatsDatabase.kt | 12 +- .../trackers/data/TrackersRepository.kt | 2 +- .../TrackersServiceSupervisor.kt | 23 ++++ .../trackers/domain/usecases/DNSBlocker.kt | 143 --------------------- .../domain/usecases/FilterHostnameUseCase.kt | 108 ++++++++++++++++ .../trackers/domain/usecases/StatisticsUseCase.kt | 12 -- .../trackers/domain/usecases/TrackersLogger.kt | 60 --------- .../domain/usecases/UpdateTrackerListUseCase.kt | 2 +- .../trackers/services/DNSBlockerService.kt | 68 ---------- 12 files changed, 153 insertions(+), 314 deletions(-) create mode 100644 trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/TrackersServiceSupervisor.kt delete mode 100644 trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt create mode 100644 trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/FilterHostnameUseCase.kt delete mode 100644 trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/TrackersLogger.kt delete mode 100644 trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt (limited to 'trackers/src') diff --git a/trackers/src/main/AndroidManifest.xml b/trackers/src/main/AndroidManifest.xml index 615d310..b980706 100644 --- a/trackers/src/main/AndroidManifest.xml +++ b/trackers/src/main/AndroidManifest.xml @@ -18,21 +18,4 @@ --> - - - - - - - - - - - - - - \ No newline at end of file diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt index 0cfb69c..34b4e7a 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt @@ -21,13 +21,13 @@ import foundation.e.advancedprivacy.data.repositories.RemoteTrackersListReposito import foundation.e.advancedprivacy.trackers.data.StatsDatabase import foundation.e.advancedprivacy.trackers.data.TrackersRepository import foundation.e.advancedprivacy.trackers.data.WhitelistRepository -import foundation.e.advancedprivacy.trackers.domain.usecases.DNSBlocker +import foundation.e.advancedprivacy.trackers.domain.usecases.FilterHostnameUseCase import foundation.e.advancedprivacy.trackers.domain.usecases.StatisticsUseCase -import foundation.e.advancedprivacy.trackers.domain.usecases.TrackersLogger import foundation.e.advancedprivacy.trackers.domain.usecases.UpdateTrackerListUseCase import org.koin.android.ext.koin.androidContext import org.koin.core.module.dsl.factoryOf import org.koin.core.module.dsl.singleOf +import org.koin.core.qualifier.named import org.koin.dsl.module val trackersModule = module { @@ -58,15 +58,13 @@ val trackersModule = module { } factory { - DNSBlocker( - context = androidContext(), - trackersLogger = get(), + FilterHostnameUseCase( trackersRepository = get(), - whitelistRepository = get() + whitelistRepository = get(), + appDesc = get(named("AdvancedPrivacy")), + context = androidContext(), + database = get(), + appListsRepository = get() ) } - - factory { - TrackersLogger(statisticsUseCase = get()) - } } diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt index c2c0768..64477b7 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt @@ -39,7 +39,7 @@ class RemoteTrackersListRepository { } return true } catch (e: IOException) { - Timber.e("While saving tracker file.", e) + Timber.e(e, "While saving tracker file.") } return false } diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt index 6aa76cf..15ff813 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt @@ -32,6 +32,10 @@ import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry. import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_TRACKER import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.TABLE_NAME import foundation.e.advancedprivacy.trackers.domain.entities.Tracker +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.withContext import timber.log.Timber import java.time.ZonedDateTime import java.time.format.DateTimeFormatter @@ -86,6 +90,9 @@ class StatsDatabase( COLUMN_NAME_APPID ) + private val _newDataAvailable = MutableSharedFlow() + val newDataAvailable: SharedFlow = _newDataAvailable + private val lock = Any() override fun onCreate(db: SQLiteDatabase) { @@ -316,7 +323,9 @@ class StatsDatabase( } } - fun logAccess(trackerId: String?, appId: String, blocked: Boolean) { + suspend fun logAccess(trackerId: String?, appId: String, blocked: Boolean) = withContext( + Dispatchers.IO + ) { synchronized(lock) { val currentHour = getCurrentHourTs() val db = writableDatabase @@ -364,6 +373,7 @@ class StatsDatabase( cursor.close() db.close() } + _newDataAvailable.emit(Unit) } private fun cursorToEntry(cursor: Cursor): StatEntry { diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt index a7d5e49..fc57a8e 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt @@ -59,7 +59,7 @@ class TrackersRepository( reader.close() inputStream.close() } catch (e: Exception) { - Timber.e("While parsing trackers in assets", e) + Timber.e(e, "While parsing trackers in assets") } } diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/TrackersServiceSupervisor.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/TrackersServiceSupervisor.kt new file mode 100644 index 0000000..d9674fc --- /dev/null +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/TrackersServiceSupervisor.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 MURENA SAS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package foundation.e.advancedprivacy.trackers.domain.externalinterfaces + +interface TrackersServiceSupervisor { + fun start(): Boolean + fun stop(): Boolean + fun isRunning(): Boolean +} diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt deleted file mode 100644 index fb08910..0000000 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2023 MURENA SAS - * Copyright (C) 2022 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package foundation.e.advancedprivacy.trackers.domain.usecases - -import android.content.Context -import android.content.pm.PackageManager -import android.net.LocalServerSocket -import android.system.ErrnoException -import android.system.Os -import android.system.OsConstants -import foundation.e.advancedprivacy.core.utils.runSuspendCatching -import foundation.e.advancedprivacy.trackers.data.TrackersRepository -import foundation.e.advancedprivacy.trackers.data.WhitelistRepository -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import timber.log.Timber -import java.io.BufferedReader -import java.io.InputStreamReader -import java.io.PrintWriter - -class DNSBlocker( - context: Context, - val trackersLogger: TrackersLogger, - private val trackersRepository: TrackersRepository, - private val whitelistRepository: WhitelistRepository -) { - private var resolverReceiver: LocalServerSocket? = null - private var eBrowserAppUid = -1 - - companion object { - private const val SOCKET_NAME = "foundation.e.advancedprivacy" - private const val E_BROWSER_DOT_SERVER = "chrome.cloudflare-dns.com" - } - - init { - initEBrowserDoTFix(context) - } - - private fun closeSocket() { - // Known bug and workaround that LocalServerSocket::close is not working well - // https://issuetracker.google.com/issues/36945762 - if (resolverReceiver != null) { - try { - Os.shutdown(resolverReceiver!!.fileDescriptor, OsConstants.SHUT_RDWR) - resolverReceiver!!.close() - resolverReceiver = null - } catch (e: ErrnoException) { - if (e.errno != OsConstants.EBADF) { - Timber.w("Socket already closed") - } else { - Timber.e(e, "Exception: cannot close DNS port on stop $SOCKET_NAME !") - } - } catch (e: Exception) { - Timber.e(e, "Exception: cannot close DNS port on stop $SOCKET_NAME !") - } - } - } - - fun listenJob(scope: CoroutineScope): Job = scope.launch(Dispatchers.IO) { - val resolverReceiver = runSuspendCatching { - LocalServerSocket(SOCKET_NAME) - }.getOrElse { - Timber.e(it, "Exception: cannot open DNS port on $SOCKET_NAME") - return@launch - } - - this@DNSBlocker.resolverReceiver = resolverReceiver - Timber.d("DNSFilterProxy running on port $SOCKET_NAME") - - while (isActive) { - runSuspendCatching { - val socket = resolverReceiver.accept() - val reader = BufferedReader(InputStreamReader(socket.inputStream)) - val line = reader.readLine() - val params = line.split(",").toTypedArray() - val output = socket.outputStream - val writer = PrintWriter(output, true) - val domainName = params[0] - val appUid = params[1].toInt() - var isBlocked = false - if (isEBrowserDoTBlockFix(appUid, domainName)) { - isBlocked = true - } else if (trackersRepository.isTracker(domainName)) { - val trackerId = trackersRepository.getTrackerId(domainName) - if (shouldBlock(appUid, trackerId)) { - writer.println("block") - isBlocked = true - } - trackersLogger.logAccess(trackerId, appUid, isBlocked) - } - if (!isBlocked) { - writer.println("pass") - } - socket.close() - }.onFailure { - if (it is CancellationException) { - closeSocket() - throw it - } else { - Timber.w(it, "Exception while listening DNS resolver") - } - } - } - } - - private fun initEBrowserDoTFix(context: Context) { - try { - eBrowserAppUid = - context.packageManager.getApplicationInfo("foundation.e.browser", 0).uid - } catch (e: PackageManager.NameNotFoundException) { - Timber.i(e, "no E Browser package found.") - } - } - - private fun isEBrowserDoTBlockFix(appUid: Int, hostname: String): Boolean { - return appUid == eBrowserAppUid && E_BROWSER_DOT_SERVER == hostname - } - - private fun shouldBlock(appUid: Int, trackerId: String?): Boolean { - return whitelistRepository.isBlockingEnabled && - !whitelistRepository.isWhiteListed(appUid, trackerId) - } -} diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/FilterHostnameUseCase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/FilterHostnameUseCase.kt new file mode 100644 index 0000000..e229cab --- /dev/null +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/FilterHostnameUseCase.kt @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2023 MURENA SAS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package foundation.e.advancedprivacy.trackers.domain.usecases + +import android.content.Context +import android.content.pm.PackageManager +import foundation.e.advancedprivacy.core.utils.runSuspendCatching +import foundation.e.advancedprivacy.data.repositories.AppListsRepository +import foundation.e.advancedprivacy.domain.entities.ApplicationDescription +import foundation.e.advancedprivacy.trackers.data.StatsDatabase +import foundation.e.advancedprivacy.trackers.data.TrackersRepository +import foundation.e.advancedprivacy.trackers.data.WhitelistRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import timber.log.Timber +import java.util.concurrent.LinkedBlockingQueue + +class FilterHostnameUseCase( + private val trackersRepository: TrackersRepository, + private val whitelistRepository: WhitelistRepository, + context: Context, + private val appDesc: ApplicationDescription, + private val database: StatsDatabase, + private val appListsRepository: AppListsRepository, +) { + private var eBrowserAppUid = -1 + + companion object { + private const val E_BROWSER_DOT_SERVER = "chrome.cloudflare-dns.com" + } + + init { + initEBrowserDoTFix(context) + } + + fun shouldBlock(hostname: String, appUid: Int = appDesc.uid): Boolean { + var isBlocked = false + + if (isEBrowserDoTBlockFix(appUid, hostname)) { + isBlocked = true + } else if (trackersRepository.isTracker(hostname)) { + val trackerId = trackersRepository.getTrackerId(hostname) + if (shouldBlock(appUid, trackerId)) { + isBlocked = true + } + queue.offer(DetectedTracker(trackerId, appUid, isBlocked)) + } + return isBlocked + } + + private fun initEBrowserDoTFix(context: Context) { + try { + eBrowserAppUid = + context.packageManager.getApplicationInfo("foundation.e.browser", 0).uid + } catch (e: PackageManager.NameNotFoundException) { + Timber.i("no E Browser package found.") + } + } + + private fun isEBrowserDoTBlockFix(appUid: Int, hostname: String): Boolean { + return appUid == eBrowserAppUid && + E_BROWSER_DOT_SERVER == hostname + } + + private fun shouldBlock(appUid: Int, trackerId: String?): Boolean { + return whitelistRepository.isBlockingEnabled && + !whitelistRepository.isWhiteListed(appUid, trackerId) + } + + private val queue = LinkedBlockingQueue() + + private suspend fun logAccess(detectedTracker: DetectedTracker) { + appListsRepository.getApp(detectedTracker.appUid)?.let { app -> + database.logAccess(detectedTracker.trackerId, app.apId, detectedTracker.wasBlocked) + } + } + + fun writeLogJob(scope: CoroutineScope): Job { + return scope.launch(Dispatchers.IO) { + while (isActive) { + runSuspendCatching { + logAccess(queue.take()) + }.onFailure { + Timber.e(it, "writeLogLoop detectedTrackersQueue.take() interrupted: ") + } + } + } + } + + inner class DetectedTracker(var trackerId: String?, var appUid: Int, var wasBlocked: Boolean) +} diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/StatisticsUseCase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/StatisticsUseCase.kt index 55efeb9..e7a84b8 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/StatisticsUseCase.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/StatisticsUseCase.kt @@ -22,24 +22,12 @@ import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription import foundation.e.advancedprivacy.trackers.data.StatsDatabase import foundation.e.advancedprivacy.trackers.domain.entities.Tracker -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow import java.time.temporal.TemporalUnit class StatisticsUseCase( private val database: StatsDatabase, private val appListsRepository: AppListsRepository ) { - private val _newDataAvailable = MutableSharedFlow() - val newDataAvailable: SharedFlow = _newDataAvailable - - suspend fun logAccess(trackerId: String?, appUid: Int, blocked: Boolean) { - appListsRepository.getApp(appUid)?.let { app -> - database.logAccess(trackerId, app.apId, blocked) - _newDataAvailable.emit(Unit) - } - } - fun getTrackersCallsOnPeriod( periodsCount: Int, periodUnit: TemporalUnit diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/TrackersLogger.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/TrackersLogger.kt deleted file mode 100644 index 411b4ab..0000000 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/TrackersLogger.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2023 MURENA SAS - * Copyright (C) 2022 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package foundation.e.advancedprivacy.trackers.domain.usecases - -import foundation.e.advancedprivacy.core.utils.runSuspendCatching -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import timber.log.Timber -import java.util.concurrent.LinkedBlockingQueue - -class TrackersLogger( - private val statisticsUseCase: StatisticsUseCase, -) { - private val queue = LinkedBlockingQueue() - - fun logAccess(trackerId: String?, appUid: Int, wasBlocked: Boolean) { - queue.offer(DetectedTracker(trackerId, appUid, wasBlocked)) - } - - fun writeLogJob(scope: CoroutineScope): Job { - return scope.launch(Dispatchers.IO) { - while (isActive) { - runSuspendCatching { - logAccess(queue.take()) - }.onFailure { - Timber.e(it, "writeLogLoop detectedTrackersQueue.take() interrupted: ") - } - } - } - } - - private suspend fun logAccess(detectedTracker: DetectedTracker) { - statisticsUseCase.logAccess( - detectedTracker.trackerId, - detectedTracker.appUid, - detectedTracker.wasBlocked - ) - } - - inner class DetectedTracker(var trackerId: String?, var appUid: Int, var wasBlocked: Boolean) -} diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt index 55da644..fa60431 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt @@ -40,7 +40,7 @@ class UpdateTrackerListUseCase( remoteTrackersListRepository.saveData(trackersRepository.eTrackerFile, api.trackers()) trackersRepository.initTrackersFile() } catch (e: Exception) { - Timber.e("While updating trackers", e) + Timber.e(e, "While updating trackers") } } } diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt deleted file mode 100644 index 25539e1..0000000 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2023 MURENA SAS - * Copyright (C) 2021 E FOUNDATION - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package foundation.e.advancedprivacy.trackers.services - -import android.app.Service -import android.content.Intent -import android.os.IBinder -import foundation.e.advancedprivacy.trackers.domain.usecases.DNSBlocker -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.cancel -import org.koin.java.KoinJavaComponent.get - -class DNSBlockerService : Service() { - companion object { - const val ACTION_START = "foundation.e.privacymodules.trackers.intent.action.START" - const val EXTRA_ENABLE_NOTIFICATION = - "foundation.e.privacymodules.trackers.intent.extra.ENABLED_NOTIFICATION" - } - - private var coroutineScope = CoroutineScope(Dispatchers.IO) - private var dnsBlocker: DNSBlocker? = null - - override fun onBind(intent: Intent): IBinder? { - throw UnsupportedOperationException("Not yet implemented") - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (ACTION_START == intent?.action) { - if (intent.getBooleanExtra(EXTRA_ENABLE_NOTIFICATION, true)) { - ForegroundStarter.startForeground(this) - } - stop() - start() - } - return START_REDELIVER_INTENT - } - - private fun start() { - coroutineScope = CoroutineScope(Dispatchers.IO) - get(DNSBlocker::class.java).apply { - this@DNSBlockerService.dnsBlocker = this - trackersLogger.writeLogJob(coroutineScope) - listenJob(coroutineScope) - } - } - - private fun stop() { - kotlin.runCatching { coroutineScope.cancel() } - dnsBlocker = null - } -} -- cgit v1.2.1