From 681fb6ae6e7e252ef7692d47dfe48922187ec380 Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Sat, 12 Aug 2023 09:09:06 +0200 Subject: [PATCH 1/5] epic18: Trackers control on standalone app (without Ipscrambling). --- .idea/vcs.xml | 1 + app/build.gradle | 2 + .../AdvancedPrivacyApplication.kt | 9 +- .../e/advancedprivacy/DependencyContainer.kt | 0 .../e/advancedprivacy/KoinModule.kt | 11 +- .../e/advancedprivacy/common/utils.kt | 22 +++ .../usecases/IpScramblingStateUseCase.kt | 3 +- .../domain/usecases/TrackersStateUseCase.kt | 20 ++- .../usecases/TrackersStatisticsUseCase.kt | 4 +- app/src/main/res/values/strings.xml | 2 +- build.gradle | 1 + .../domain/entities/ServiceState.kt | 5 + gradle/libs.versions.toml | 6 +- ipscrambling/build.gradle | 2 +- settings.gradle | 2 + trackers/src/main/AndroidManifest.xml | 17 -- .../e/advancedprivacy/trackers/KoinModule.kt | 18 +- .../trackers/data/StatsDatabase.kt | 12 +- .../ITrackersServiceSupervisor.kt | 7 + .../domain/usecases/FilterHostnameUseCase.kt | 94 ++++++++++ .../domain/usecases/StatisticsUseCase.kt | 19 +- .../domain/usecases/TrackersLogger.kt | 60 ------- trackersservicee/.gitignore | 1 + trackersservicee/build.gradle | 43 +++++ trackersservicee/consumer-rules.pro | 0 trackersservicee/proguard-rules.pro | 21 +++ trackersservicee/src/main/AndroidManifest.xml | 35 ++++ .../trackers/service}/DNSBlocker.kt | 53 +----- .../trackers/service/TrackersService.kt | 21 +-- .../service/TrackersServiceSupervisor.kt | 30 ++++ trackersservicestandalone/.gitignore | 1 + trackersservicestandalone/build.gradle | 43 +++++ trackersservicestandalone/consumer-rules.pro | 0 trackersservicestandalone/proguard-rules.pro | 21 +++ .../src/main/AndroidManifest.xml | 23 +++ .../trackers/service/Config.kt | 29 +++ .../trackers/service/TrackersService.kt | 166 ++++++++++++++++++ .../service/TrackersServiceSupervisor.kt | 48 +++++ .../trackers/service/TunLooper.kt | 148 ++++++++++++++++ .../data/NetworkDNSAddressRepository.kt | 45 +++++ .../service/data/RequestDNSRepository.kt | 34 ++++ .../service/usecases/ResolveDNSUseCase.kt | 45 +++++ 42 files changed, 952 insertions(+), 172 deletions(-) create mode 100644 app/src/main/java/foundation/e/advancedprivacy/DependencyContainer.kt create mode 100644 app/src/main/java/foundation/e/advancedprivacy/common/utils.kt create mode 100644 core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt create mode 100644 trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.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 create mode 100644 trackersservicee/.gitignore create mode 100644 trackersservicee/build.gradle create mode 100644 trackersservicee/consumer-rules.pro create mode 100644 trackersservicee/proguard-rules.pro create mode 100644 trackersservicee/src/main/AndroidManifest.xml rename {trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases => trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service}/DNSBlocker.kt (65%) rename trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt => trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt (76%) create mode 100644 trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt create mode 100644 trackersservicestandalone/.gitignore create mode 100644 trackersservicestandalone/build.gradle create mode 100644 trackersservicestandalone/consumer-rules.pro create mode 100644 trackersservicestandalone/proguard-rules.pro create mode 100644 trackersservicestandalone/src/main/AndroidManifest.xml create mode 100644 trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt create mode 100644 trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt create mode 100644 trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt create mode 100644 trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt create mode 100644 trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt create mode 100644 trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt create mode 100644 trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f..b3ceaf3f 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index ef54d456..8a64d6d0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -152,6 +152,8 @@ dependencies { implementation project(':trackers') implementation project(':ipscrambling') + eImplementation project(':trackersservicee') + standaloneImplementation project(':trackersservicestandalone') implementation ( libs.e.elib, diff --git a/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt b/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt index 0af2a0e9..71fef005 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt @@ -18,7 +18,6 @@ package foundation.e.advancedprivacy import android.app.Application -import android.content.Intent import foundation.e.advancedprivacy.common.WarningDialog import foundation.e.advancedprivacy.domain.usecases.FakeLocationStateUseCase import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase @@ -27,7 +26,6 @@ import foundation.e.advancedprivacy.domain.usecases.ShowFeaturesWarningUseCase import foundation.e.advancedprivacy.domain.usecases.TrackersStateUseCase import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule -import foundation.e.advancedprivacy.trackers.services.DNSBlockerService import foundation.e.advancedprivacy.trackers.services.UpdateTrackersWorker import foundation.e.lib.telemetry.Telemetry import kotlinx.coroutines.CoroutineScope @@ -70,12 +68,7 @@ class AdvancedPrivacyApplication : Application() { ) get(IpScramblingStateUseCase::class.java) - get(FakeLocationStateUseCase::class.java) get(TrackersStateUseCase::class.java) - - val intent = Intent(this, DNSBlockerService::class.java) - intent.action = DNSBlockerService.ACTION_START - intent.putExtra(DNSBlockerService.EXTRA_ENABLE_NOTIFICATION, false) - startService(intent) + get(FakeLocationStateUseCase::class.java) } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/DependencyContainer.kt b/app/src/main/java/foundation/e/advancedprivacy/DependencyContainer.kt new file mode 100644 index 00000000..e69de29b diff --git a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt index 3fbb6360..d88edade 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt @@ -40,6 +40,9 @@ import foundation.e.advancedprivacy.features.trackers.TrackersViewModel import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersViewModel import foundation.e.advancedprivacy.ipscrambler.ipScramblerModule import foundation.e.advancedprivacy.permissions.externalinterfaces.PermissionsPrivacyModule +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.service.TrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.service.trackerServiceModule import foundation.e.advancedprivacy.trackers.trackersModule import org.koin.android.ext.koin.androidContext import org.koin.androidx.viewmodel.dsl.viewModel @@ -49,7 +52,7 @@ import org.koin.core.qualifier.named import org.koin.dsl.module val appModule = module { - includes(coreModule, trackersModule, fakelocationModule, ipScramblerModule) + includes(coreModule, trackersModule, fakelocationModule, ipScramblerModule, trackerServiceModule) factory { androidContext().resources } single { @@ -123,6 +126,12 @@ val appModule = module { PermissionsPrivacyModule(context = androidContext()) } + single { + TrackersServiceSupervisor( + context = androidContext(), + ) + } + viewModel { parameters -> val appListUseCase: AppListUseCase = get() val app = appListUseCase.getApp(parameters.get()) diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/utils.kt b/app/src/main/java/foundation/e/advancedprivacy/common/utils.kt new file mode 100644 index 00000000..acd16ca3 --- /dev/null +++ b/app/src/main/java/foundation/e/advancedprivacy/common/utils.kt @@ -0,0 +1,22 @@ +/* + * 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.common + +import foundation.e.advancedprivacy.BuildConfig + +val isStandaloneFlavor = BuildConfig.FLAVOR == "standalone" diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt index 27e7fe40..d733faea 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt @@ -19,6 +19,7 @@ package foundation.e.advancedprivacy.domain.usecases import android.content.Intent +import foundation.e.advancedprivacy.common.isStandaloneFlavor import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription @@ -190,7 +191,7 @@ class IpScramblingStateUseCase( fun startIpScrambling() { localStateRepository.internetPrivacyMode.value = HIDE_IP_LOADING - ipScramblerModule.start(enableNotification = false) // change the false ? + ipScramblerModule.start(enableNotification = isStandaloneFlavor) } private fun map(status: IpScramblerModule.Status): InternetPrivacyMode { diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt index ed15a414..0fe0c52b 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt @@ -17,11 +17,13 @@ package foundation.e.advancedprivacy.domain.usecases +import foundation.e.advancedprivacy.common.isStandaloneFlavor import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription import foundation.e.advancedprivacy.trackers.data.WhitelistRepository import foundation.e.advancedprivacy.trackers.domain.entities.Tracker +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -29,7 +31,8 @@ class TrackersStateUseCase( private val whitelistRepository: WhitelistRepository, private val localStateRepository: LocalStateRepository, private val appListsRepository: AppListsRepository, - coroutineScope: CoroutineScope + private val trackersServiceSupervisor: ITrackersServiceSupervisor, + coroutineScope: CoroutineScope, ) { init { coroutineScope.launch { @@ -38,6 +41,21 @@ class TrackersStateUseCase( updateAllTrackersBlockedState() } } + + if (isStandaloneFlavor) { + coroutineScope.launch { + localStateRepository.blockTrackers.collect { enabled -> + if (enabled) { + // TODO: VPnService intent handling permission. + trackersServiceSupervisor.start() + } else { + trackersServiceSupervisor.stop() + } + } + } + } else { + trackersServiceSupervisor.start() + } } private fun updateAllTrackersBlockedState() { diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStatisticsUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStatisticsUseCase.kt index b0c9f391..3d6ade0f 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStatisticsUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStatisticsUseCase.kt @@ -24,6 +24,7 @@ import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.domain.entities.AppWithCounts import foundation.e.advancedprivacy.domain.entities.ApplicationDescription import foundation.e.advancedprivacy.domain.entities.TrackersPeriodicStatistics +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.entities.Tracker @@ -44,6 +45,7 @@ class TrackersStatisticsUseCase( private val whitelistRepository: WhitelistRepository, private val trackersRepository: TrackersRepository, private val appListsRepository: AppListsRepository, + private val statsDatabase: StatsDatabase, private val resources: Resources ) { fun initAppList() { @@ -52,7 +54,7 @@ class TrackersStatisticsUseCase( @OptIn(FlowPreview::class) fun listenUpdates(debounce: Duration = 1.seconds) = - statisticsUseCase.newDataAvailable + statsDatabase.newDataAvailable .throttleFirst(windowDuration = debounce) .onStart { emit(Unit) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fac1f753..c23b0591 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - Advanced Privacy + Advanced Privacy_6 Close diff --git a/build.gradle b/build.gradle index a57ee217..cd192ee3 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,7 @@ plugins { alias libs.plugins.android.application apply false alias libs.plugins.kotlin.kapt apply false alias libs.plugins.androidx.navigation.safeargs apply false + alias libs.plugins.android.library apply false } allprojects { diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt new file mode 100644 index 00000000..d80cdf57 --- /dev/null +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt @@ -0,0 +1,5 @@ +package foundation.e.advancedprivacy.domain.entities + +enum class ServiceState { + OFF, ON, STARTING, STOPPING +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9925d41..00bf753e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,6 +9,7 @@ androidx-lifecycle = "2.5.0" androidx-room = "2.3.0" orbotservice = "orbot-16.6.3-1" retrofit = "2.9.0" +pcap4j = "1.8.2" [libraries] @@ -42,6 +43,8 @@ leakcanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", v maplibre = { group = "org.maplibre.gl", name = "android-sdk", version = "10.2.0" } mockk = { group = "io.mockk", name = "mockk", version = "1.10.5" } mpandroidcharts = { group = "com.github.PhilJay", name = "MPAndroidChart", version = "v3.1.0" } +pcap4j = { group = "org.pcap4j", name = "pcap4j-core", version.ref = "pcap4j" } +pcap4j-packetfactory-static = { group = "org.pcap4j", name = "pcap4j-packetfactory-static", version.ref = "pcap4j" } retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } retrofit-scalars = { group = "com.squareup.retrofit2", name = "converter-scalars", version.ref = "retrofit" } timber = { group = "com.jakewharton.timber", name = "timber", version = "5.0.1" } @@ -50,10 +53,11 @@ timber = { group = "com.jakewharton.timber", name = "timber", version = "5.0.1" koin = ["koin-core", "koin-android"] kotlin-android-coroutines = ["androidx-core-ktx", "kotlinx-coroutines"] - +pcap4j = ["pcap4j", "pcap4j-packetfactory-static"] [plugins] android-application = { id = "com.android.application", version = "7.2.1" } +android-library = { id = "com.android.library", version = "7.2.1" } androidx-navigation-safeargs = { id = "androidx.navigation.safeargs.kotlin", version.ref = "androidx-navigation" } benmanes-versions = { id = "com.github.ben-manes.versions", version = "0.38.0" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } diff --git a/ipscrambling/build.gradle b/ipscrambling/build.gradle index 39efce74..b99f9c17 100644 --- a/ipscrambling/build.gradle +++ b/ipscrambling/build.gradle @@ -52,5 +52,5 @@ dependencies { libs.androidx.localbroadcast, ) implementation libs.e.orbotservice - //implementation project(':ipscrambling:orbotservice') +// implementation project(':ipscrambling:orbotservice') } diff --git a/settings.gradle b/settings.gradle index 0b4940e5..f0b781df 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,6 +19,8 @@ include ':permissionse' include ':permissionse:libs:hidden-apis-stub' include ':ipscrambling' include ':ipscrambling:orbotservice' +include ':trackersservicestandalone' +include ':trackersservicee' dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) diff --git a/trackers/src/main/AndroidManifest.xml b/trackers/src/main/AndroidManifest.xml index 615d3106..b9807063 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 0cfb69cf..34b4e7a8 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/StatsDatabase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt index 6aa76cfd..15ff8137 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/domain/externalinterfaces/ITrackersServiceSupervisor.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt new file mode 100644 index 00000000..159f1ce1 --- /dev/null +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt @@ -0,0 +1,7 @@ +package foundation.e.advancedprivacy.trackers.domain.externalinterfaces + +interface ITrackersServiceSupervisor { + fun start(): Boolean + fun stop(): Boolean + fun isRunning(): Boolean +} 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 00000000..77171600 --- /dev/null +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/FilterHostnameUseCase.kt @@ -0,0 +1,94 @@ +package foundation.e.advancedprivacy.trackers.domain.usecases + +import android.content.Context +import android.content.pm.PackageManager +import android.util.Log +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 { + Log.d("epic18", "shouldblock: $hostname, appUid: $appUid") + 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 55efeb99..a6753db7 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,23 +22,22 @@ 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 + // 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) - } - } + // suspend fun logAccess(trackerId: String?, appUid: Int, blocked: Boolean) { + // appListsRepository.getApp(appUid)?.let { app -> + // Log.d("epic18", "logAccess: trackerId: $trackerId, appUid: $appUid, blocked: $blocked") + // database.logAccess(trackerId, app.apId, blocked) + // _newDataAvailable.emit(Unit) + // } + // } fun getTrackersCallsOnPeriod( periodsCount: Int, 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 411b4ab6..00000000 --- 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/trackersservicee/.gitignore b/trackersservicee/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/trackersservicee/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/trackersservicee/build.gradle b/trackersservicee/build.gradle new file mode 100644 index 00000000..f7725bfb --- /dev/null +++ b/trackersservicee/build.gradle @@ -0,0 +1,43 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' +} + +android { + namespace 'foundation.e.advancedprivacy.trackers.service' + compileSdk 33 + + defaultConfig { + minSdk 24 + targetSdk 33 + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + implementation project(":core") + implementation project(":trackers") + + implementation( + libs.androidx.core.ktx, + libs.bundles.koin, + libs.kotlinx.coroutines, + libs.timber, + ) +} diff --git a/trackersservicee/consumer-rules.pro b/trackersservicee/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/trackersservicee/proguard-rules.pro b/trackersservicee/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/trackersservicee/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/trackersservicee/src/main/AndroidManifest.xml b/trackersservicee/src/main/AndroidManifest.xml new file mode 100644 index 00000000..22904321 --- /dev/null +++ b/trackersservicee/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/DNSBlocker.kt similarity index 65% rename from trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt rename to trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/DNSBlocker.kt index fb089103..ead3dbd8 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt +++ b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/DNSBlocker.kt @@ -16,17 +16,14 @@ * along with this program. If not, see . */ -package foundation.e.advancedprivacy.trackers.domain.usecases +package foundation.e.advancedprivacy.trackers.service -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 foundation.e.advancedprivacy.trackers.domain.usecases.FilterHostnameUseCase import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -39,21 +36,12 @@ import java.io.InputStreamReader import java.io.PrintWriter class DNSBlocker( - context: Context, - val trackersLogger: TrackersLogger, - private val trackersRepository: TrackersRepository, - private val whitelistRepository: WhitelistRepository + val filterHostnameUseCase: FilterHostnameUseCase ) { 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() { @@ -88,7 +76,7 @@ class DNSBlocker( Timber.d("DNSFilterProxy running on port $SOCKET_NAME") while (isActive) { - runSuspendCatching { + runCatching { val socket = resolverReceiver.accept() val reader = BufferedReader(InputStreamReader(socket.inputStream)) val line = reader.readLine() @@ -97,18 +85,9 @@ class DNSBlocker( 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) { + if (filterHostnameUseCase.shouldBlock(domainName, appUid)) { + writer.println("block") + } else { writer.println("pass") } socket.close() @@ -122,22 +101,4 @@ class DNSBlocker( } } } - - 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/services/DNSBlockerService.kt b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt similarity index 76% rename from trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt rename to trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt index 25539e18..55a69e2d 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt +++ b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt @@ -15,27 +15,24 @@ * 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 +package foundation.e.advancedprivacy.trackers.service 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() { +class TrackersService : 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 + var coroutineScope = CoroutineScope(Dispatchers.IO) + } override fun onBind(intent: Intent): IBinder? { throw UnsupportedOperationException("Not yet implemented") @@ -43,9 +40,9 @@ class DNSBlockerService : Service() { 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) - } + // if (intent.getBooleanExtra(EXTRA_ENABLE_NOTIFICATION, true)) { + // ForegroundStarter.startForeground(this) + // } stop() start() } @@ -55,14 +52,12 @@ class DNSBlockerService : Service() { private fun start() { coroutineScope = CoroutineScope(Dispatchers.IO) get(DNSBlocker::class.java).apply { - this@DNSBlockerService.dnsBlocker = this - trackersLogger.writeLogJob(coroutineScope) + filterHostnameUseCase.writeLogJob(coroutineScope) listenJob(coroutineScope) } } private fun stop() { kotlin.runCatching { coroutineScope.cancel() } - dnsBlocker = null } } diff --git a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt new file mode 100644 index 00000000..4506c4de --- /dev/null +++ b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt @@ -0,0 +1,30 @@ +package foundation.e.advancedprivacy.trackers.service + +import android.content.Context +import android.content.Intent +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.service.TrackersService.Companion.ACTION_START +import kotlinx.coroutines.isActive +import org.koin.core.module.dsl.factoryOf +import org.koin.dsl.module + +class TrackersServiceSupervisor(private val context: Context) : ITrackersServiceSupervisor { + + override fun start(): Boolean { + val intent = Intent(context, TrackersService::class.java) + intent.action = ACTION_START + return context.startService(intent) != null + } + + override fun stop(): Boolean { + return context.stopService(Intent(context, TrackersService::class.java)) + } + + override fun isRunning(): Boolean { + return TrackersService.coroutineScope.isActive + } +} + +val trackerServiceModule = module { + factoryOf(::DNSBlocker) +} diff --git a/trackersservicestandalone/.gitignore b/trackersservicestandalone/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/trackersservicestandalone/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/trackersservicestandalone/build.gradle b/trackersservicestandalone/build.gradle new file mode 100644 index 00000000..d5df422c --- /dev/null +++ b/trackersservicestandalone/build.gradle @@ -0,0 +1,43 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' +} + +android { + compileSdk 32 + + defaultConfig { + minSdk 26 + targetSdk 32 + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + implementation project(":core") + implementation project(":trackers") + + implementation( + libs.androidx.core.ktx, + libs.bundles.koin, + libs.bundles.pcap4j, + libs.kotlinx.coroutines, + libs.timber, + ) +} diff --git a/trackersservicestandalone/consumer-rules.pro b/trackersservicestandalone/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/trackersservicestandalone/proguard-rules.pro b/trackersservicestandalone/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/trackersservicestandalone/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/trackersservicestandalone/src/main/AndroidManifest.xml b/trackersservicestandalone/src/main/AndroidManifest.xml new file mode 100644 index 00000000..0047c165 --- /dev/null +++ b/trackersservicestandalone/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt new file mode 100644 index 00000000..bf71355c --- /dev/null +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt @@ -0,0 +1,29 @@ +package foundation.e.advancedprivacy.trackers.service + +internal object Config { + const val SESSION_NAME = "TrackersService" + + const val FALLBACK_DNS = "1.1.1.1" + const val VERBOSE = true + + const val VIRTUALDNS_IPV4 = "10.10.10.10" + const val VIRTUALDNS_IPV6 = "fdc8:1095:91e1:aaaa:aaaa:aaaa:aaaa:aaa1" + const val ADDRESS_IPV4 = "10.0.2.15" + const val ADDRESS_IPV6 = "fdc8:1095:91e1:aaaa:aaaa:aaaa:aaaa:aaa2" + + const val BLOCKED_IPV4 = "127.0.0.1" + const val BLOCKED_IPV6 = "::1" + + const val MTU = 3000 + const val LOCAL_RESOLVER_TTL = 60 + + // + const val MAX_RESOLVER_COUNT = 100 + + val DNS_SERVER_TO_CATCH_IPV4 = listOf( + "8.8.8.8", "8.8.4.4", "1.1.1.1" + ) + val DNS_SERVER_TO_CATCH_IPV6 = listOf( + "2001:4860:4860::8888", "2001:4860:4860::8844" + ) +} diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt new file mode 100644 index 00000000..e91dfe26 --- /dev/null +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt @@ -0,0 +1,166 @@ +package foundation.e.advancedprivacy.trackers.service + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.content.Intent +import android.net.VpnService +import android.os.Build +import android.os.ParcelFileDescriptor +import foundation.e.advancedprivacy.domain.entities.ServiceState +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.service.Config.DNS_SERVER_TO_CATCH_IPV4 +import foundation.e.advancedprivacy.trackers.service.Config.DNS_SERVER_TO_CATCH_IPV6 +import foundation.e.advancedprivacy.trackers.service.Config.SESSION_NAME +import foundation.e.advancedprivacy.trackers.service.data.NetworkDNSAddressRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import org.koin.java.KoinJavaComponent.get +import timber.log.Timber + +class TrackersService : VpnService() { + companion object { + var coroutineScope = CoroutineScope(Dispatchers.IO) + + fun start(context: Context) { + prepare(context) + val intent = Intent(context, TrackersService::class.java) + context.startService(intent) + } + } + + private val networkDNSAddressRepository: NetworkDNSAddressRepository = get(NetworkDNSAddressRepository::class.java) + private val trackersServiceSupervisor: TrackersServiceSupervisor = get( + ITrackersServiceSupervisor::class.java + ) as TrackersServiceSupervisor + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + startVPN() + + startForeground(1, createNotification(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)) + + trackersServiceSupervisor.state.value = ServiceState.ON + + return START_STICKY + } + + override fun onDestroy() { + networkDNSAddressRepository.stop() + trackersServiceSupervisor.state.value = ServiceState.OFF + super.onDestroy() + } + + private fun startVPN() { + val vpnInterface = initVPN() + + if (vpnInterface != null) { + networkDNSAddressRepository.start() + + coroutineScope = CoroutineScope(Dispatchers.IO) + get(TunLooper::class.java).apply { + listenJob(vpnInterface, coroutineScope) + } + } else Timber.e("Cannot get VPN interface") + } + + private fun initVPN(): ParcelFileDescriptor? { + val builder = Builder() + builder.setSession(SESSION_NAME) + // IPV4: + builder + .addAddress(Config.ADDRESS_IPV4, 24) + .addDnsServer(Config.VIRTUALDNS_IPV4) + .addRoute(Config.VIRTUALDNS_IPV4, 32) + + // IPV6 + builder + .addAddress(Config.ADDRESS_IPV6, 48) + .addDnsServer(Config.VIRTUALDNS_IPV6) + .addRoute(Config.VIRTUALDNS_IPV6, 128) + + DNS_SERVER_TO_CATCH_IPV4.forEach { + builder.addRoute(it, 32) + } + DNS_SERVER_TO_CATCH_IPV6.forEach { + builder.addRoute(it, 128) + } + + // TODO: block private DNS. + + // this app itself should bypass VPN in order to prevent endless recursion + builder.addDisallowedApplication(packageName) + + // TODO 20230821: seens in privateDNSFilter : +// // Android 7/8 has an issue with VPN in combination with some google apps - bypass the filter +// if (Build.VERSION.SDK_INT >= 24 && Build.VERSION.SDK_INT <= 27) { // Android 7/8 +// if (explicitOp) Logger.getLogger().logLine("Running on SDK" + Build.VERSION.SDK_INT) +// excludeApp("com.android.vending", builder) //white list play store +// excludeApp("com.google.android.apps.docs", builder) //white list google drive +// excludeApp("com.google.android.apps.photos", builder) //white list google photos +// excludeApp("com.google.android.gm", builder) //white list gmail +// excludeApp("com.google.android.apps.translate", builder) //white list google translate +// } + + builder.setBlocking(true) + + builder.setMtu(Config.MTU) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + builder.setMetered(false) // take over defaults from underlying network + } + + // Set the PendingIntent to an activity for users to configure the VPN connection. If it is not set, the button to configure will not be shown in system-managed dialogs. +// return builder.setConfigureIntent(pendingIntent).establish() + + return builder.establish() + } + + // registerNEtworkCallback . + + // private fun getDNSviaConnectivityManager(): Array { + // val result = HashSet() + // val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager + // var networks: Array? = getConnectedNetworks( + // connectivityManager, + // ConnectivityManager.TYPE_WIFI + // ) // prefer WiFi + // + // if (networks?.size == 0) networks = getConnectedNetworks( + // connectivityManager, + // -1 + // ) // fallback all networks + // + // networks?.forEach { network -> + // val linkProperties = connectivityManager.getLinkProperties(network) + // if (linkProperties != null) { + // val dnsList = linkProperties.dnsServers + // for (i in dnsList.indices) { + // val adr = dnsList[i].hostAddress + // if (adr != Config.VIRTUALDNS_IPV4 && adr != Config.VIRTUALDNS_IPV6) result.add( + // adr + // ) + // } + // } else Timber.w("Cannot get link properties for $network") + // } + // return result.toTypedArray() + // } + // + // private fun getConnectedNetworks(conMan: ConnectivityManager, type: Int): Array { + // val nwList = ArrayList() + // val nw = conMan.allNetworks + // for (i in nw.indices) { + // val ni = conMan.getNetworkInfo(nw[i]) + // if (ni != null && (ni.type == type || type == -1) && ni.isConnected) nwList.add(nw[i]) + // } + // return nwList.toTypedArray() + // } + + private fun createNotification(notificationManager: NotificationManager): Notification { + val channel = NotificationChannel("foreground", "ForegorundNotif", NotificationManager.IMPORTANCE_LOW) + notificationManager.createNotificationChannel(channel) + return Notification.Builder(this, "foreground") + .setContentTitle("TunProxyVpnService") + .setContentText("Running") + .build() + } +} diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt new file mode 100644 index 00000000..6efd39f2 --- /dev/null +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt @@ -0,0 +1,48 @@ +package foundation.e.advancedprivacy.trackers.service + +import android.content.Context +import android.content.Intent +import foundation.e.advancedprivacy.domain.entities.ServiceState +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.service.data.NetworkDNSAddressRepository +import foundation.e.advancedprivacy.trackers.service.data.RequestDNSRepository +import foundation.e.advancedprivacy.trackers.service.usecases.ResolveDNSUseCase +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import org.koin.core.module.dsl.singleOf +import org.koin.dsl.module + +class TrackersServiceSupervisor(private val context: Context) : ITrackersServiceSupervisor { + internal val state: MutableStateFlow = MutableStateFlow(ServiceState.OFF) + + override fun start(): Boolean { + return if (!isRunning()) { + state.value = ServiceState.STARTING + TrackersService.start(context) + true + } else false + } + + override fun stop(): Boolean { + return when (state.value) { + ServiceState.ON -> { + state.value = ServiceState.STOPPING + kotlin.runCatching { TrackersService.coroutineScope.cancel() } + context.stopService(Intent(context, TrackersService::class.java)) + true + } + else -> false + } + } + + override fun isRunning(): Boolean { + return state.value != ServiceState.OFF + } +} + +val trackerServiceModule = module { + singleOf(::NetworkDNSAddressRepository) + singleOf(::RequestDNSRepository) + singleOf(::ResolveDNSUseCase) + singleOf(::TunLooper) +} diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt new file mode 100644 index 00000000..20b7a501 --- /dev/null +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt @@ -0,0 +1,148 @@ +package foundation.e.advancedprivacy.trackers.service + +import android.os.ParcelFileDescriptor +import foundation.e.advancedprivacy.trackers.service.usecases.ResolveDNSUseCase +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 org.pcap4j.packet.DnsPacket +import org.pcap4j.packet.IpPacket +import org.pcap4j.packet.IpSelector +import org.pcap4j.packet.IpV4Packet +import org.pcap4j.packet.IpV6Packet +import org.pcap4j.packet.UdpPacket +import org.pcap4j.packet.namednumber.IpNumber +import org.pcap4j.packet.namednumber.UdpPort +import timber.log.Timber +import java.io.DataOutputStream +import java.io.FileInputStream +import java.io.FileOutputStream +import java.io.IOException +import java.net.Inet6Address +import java.util.Arrays + +class TunLooper( + private val resolveDNSUseCase: ResolveDNSUseCase, +) { + private var vpnInterface: ParcelFileDescriptor? = null + private var fis: FileInputStream? = null + private var fos: DataOutputStream? = null + + private fun closeStreams() { + fis?.close() + fis = null + + fos?.close() + fos = null + + vpnInterface?.close() + vpnInterface = null + } + + fun listenJob( + vpnInterface: ParcelFileDescriptor, + scope: CoroutineScope + ): Job = scope.launch(Dispatchers.IO) { + this@TunLooper.vpnInterface = vpnInterface + val fis = FileInputStream(vpnInterface.fileDescriptor) + this@TunLooper.fis = fis + fos = DataOutputStream(FileOutputStream(vpnInterface.fileDescriptor)) + + while (isActive) { + runCatching { + val buffer = ByteArray(Config.MTU) + val pLen = fis.read(buffer) + + if (pLen > 0) { + scope.launch { handleIpPacket(buffer, pLen) } + } + }.onFailure { + if (it is CancellationException) { + closeStreams() + throw it + } else { + Timber.w(it, "while reading from VPN fd") + } + } + } + } + + private suspend fun handleIpPacket(buffer: ByteArray, pLen: Int) { + val pdata = Arrays.copyOf(buffer, pLen) + try { + val packet = IpSelector.newPacket(pdata, 0, pdata.size) + if (packet is IpPacket) { + val ipPacket = packet + if (isPacketDNS(ipPacket)) handleDnsPacket(ipPacket) + } + } catch (e: Exception) { + Timber.w("Can't parse packet, ignore it.", e) + } + } + + private fun isPacketDNS(p: IpPacket): Boolean { + if (p.header.protocol === IpNumber.UDP) { + val up = p.payload as UdpPacket + return up.header.dstPort === UdpPort.DOMAIN + } + return false + } + + private suspend fun handleDnsPacket(ipPacket: IpPacket) { + try { + val udpPacket = ipPacket.payload as UdpPacket + val dnsRequest = udpPacket.payload as DnsPacket + val dnsResponse = resolveDNSUseCase.processDNS(dnsRequest) + + if (dnsResponse != null) { + val dnsBuilder = dnsResponse.builder + + val udpBuilder = UdpPacket.Builder(udpPacket) + .srcPort(udpPacket.header.dstPort) + .dstPort(udpPacket.header.srcPort) + .srcAddr(ipPacket.getHeader().getDstAddr()) + .dstAddr(ipPacket.getHeader().getSrcAddr()) + .correctChecksumAtBuild(true) + .correctLengthAtBuild(true) + .payloadBuilder(dnsBuilder) + val respPacket: IpPacket? = if (ipPacket is IpV4Packet) { + val ipV4Packet = ipPacket + val ipv4Builder = IpV4Packet.Builder() + ipv4Builder + .version(ipV4Packet.header.version) + .protocol(ipV4Packet.header.protocol) + .tos(ipV4Packet.header.tos) + .srcAddr(ipV4Packet.header.dstAddr) + .dstAddr(ipV4Packet.header.srcAddr) + .correctChecksumAtBuild(true) + .correctLengthAtBuild(true) + .dontFragmentFlag(ipV4Packet.header.dontFragmentFlag) + .reservedFlag(ipV4Packet.header.reservedFlag) + .moreFragmentFlag(ipV4Packet.header.moreFragmentFlag) + .ttl(Integer.valueOf(64).toByte()) + .payloadBuilder(udpBuilder) + ipv4Builder.build() + } else if (ipPacket is IpV6Packet) { + IpV6Packet.Builder(ipPacket as IpV6Packet?) + .srcAddr(ipPacket.getHeader().getDstAddr() as Inet6Address) + .dstAddr(ipPacket.getHeader().getSrcAddr() as Inet6Address) + .payloadBuilder(udpBuilder) + .build() + } else null + + respPacket?.let { + try { + fos?.write(it.rawData) + } catch (e: IOException) { + Timber.e("error writing to VPN fd", e) + } + } + } + } catch (ioe: java.lang.Exception) { + Timber.e("could not parse DNS packet: $ioe") + } + } +} diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt new file mode 100644 index 00000000..f34a508f --- /dev/null +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt @@ -0,0 +1,45 @@ +package foundation.e.advancedprivacy.trackers.service.data + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkRequest +import foundation.e.advancedprivacy.trackers.service.Config +import timber.log.Timber +import java.net.InetAddress + +class NetworkDNSAddressRepository(private val context: Context) { + private val connectivityManager: ConnectivityManager = + context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + fun start() { + connectivityManager.registerNetworkCallback( + NetworkRequest.Builder().build(), + networkCallback + ) + } + + fun stop() { + kotlin.runCatching { + connectivityManager.unregisterNetworkCallback(networkCallback) + } + } + + var dnsAddress: InetAddress = InetAddress.getByName(Config.FALLBACK_DNS) + private set + + private val networkCallback = object : ConnectivityManager.NetworkCallback() { + override fun onAvailable(network: Network) { + super.onAvailable(network) + val linkProperties = connectivityManager.getLinkProperties(network) + if (linkProperties != null) { + val dnsList = linkProperties.dnsServers + for (i in dnsList.indices) { + val adr = dnsList[i].hostAddress + if (adr != Config.VIRTUALDNS_IPV4 && adr != Config.VIRTUALDNS_IPV6) { + dnsAddress = InetAddress.getByName(adr) + } + } + } else Timber.w("Cannot get link properties for $network") + } + } +} diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt new file mode 100644 index 00000000..c8e72082 --- /dev/null +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt @@ -0,0 +1,34 @@ +package foundation.e.advancedprivacy.trackers.service.data + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.pcap4j.packet.DnsPacket +import org.pcap4j.packet.IllegalRawDataException +import timber.log.Timber +import java.net.DatagramPacket +import java.net.DatagramSocket + +class RequestDNSRepository { + + suspend fun processDNS(request: DatagramPacket): DnsPacket? = withContext(Dispatchers.IO) { + // val payload = dnsRequest.rawData + // var packet = DatagramPacket(payload, payload.size, dnsAddress, dnsPort) + var response: DnsPacket? = null + val datagramSocket = DatagramSocket() + datagramSocket.send(request) + + // Await response from DNS server + val buf = ByteArray(1024) + val packet = DatagramPacket(buf, buf.size) + datagramSocket.receive(packet) + val dnsResp = packet.data + if (dnsResp != null) { + try { + response = DnsPacket.newPacket(dnsResp, 0, dnsResp.size) + } catch (e: IllegalRawDataException) { + Timber.e("Can't parse DNS response", e) + } + } + response + } +} diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt new file mode 100644 index 00000000..55809496 --- /dev/null +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt @@ -0,0 +1,45 @@ +package foundation.e.advancedprivacy.trackers.service.usecases + +import foundation.e.advancedprivacy.trackers.domain.usecases.FilterHostnameUseCase +import foundation.e.advancedprivacy.trackers.service.data.NetworkDNSAddressRepository +import foundation.e.advancedprivacy.trackers.service.data.RequestDNSRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.GlobalScope +import org.pcap4j.packet.DnsPacket +import org.pcap4j.packet.namednumber.DnsRCode +import timber.log.Timber +import java.io.IOException +import java.net.DatagramPacket + +@OptIn(DelicateCoroutinesApi::class) +class ResolveDNSUseCase( + private val networkDNSAddressRepository: NetworkDNSAddressRepository, + private val filterHostnameUseCase: FilterHostnameUseCase, + private val requestDNSRepository: RequestDNSRepository, + private val scope: CoroutineScope = GlobalScope +) { + private val DNS_PORT = 53 + + init { + filterHostnameUseCase.writeLogJob(scope) + } + + @Throws(IOException::class) + suspend fun processDNS(dnsRequest: DnsPacket): DnsPacket? { + try { + val host = dnsRequest.header.questions[0].qName.name + if (filterHostnameUseCase.shouldBlock(host)) { + return dnsRequest.builder + .rCode(DnsRCode.NX_DOMAIN) + .response(true).build() + } + } catch (e: Exception) { + Timber.e("Can't find host", e) + } + + val payload = dnsRequest.rawData + val packet = DatagramPacket(payload, payload.size, networkDNSAddressRepository.dnsAddress, DNS_PORT) + return requestDNSRepository.processDNS(packet) + } +} -- GitLab From 213947688f055228bc224e0547a371124c8c1ddc Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Thu, 28 Sep 2023 09:16:48 +0200 Subject: [PATCH 2/5] Auto review. --- .idea/vcs.xml | 1 - app/src/main/res/values/strings.xml | 2 +- .../domain/entities/ServiceState.kt | 16 ++++ ipscrambling/build.gradle | 2 +- settings.gradle | 2 +- .../ITrackersServiceSupervisor.kt | 16 ++++ .../domain/usecases/FilterHostnameUseCase.kt | 16 ++++ .../domain/usecases/StatisticsUseCase.kt | 11 --- .../trackers/service/DNSBlocker.kt | 2 +- .../trackers/service/TrackersService.kt | 5 -- .../service/TrackersServiceSupervisor.kt | 16 ++++ .../src/main/AndroidManifest.xml | 16 ++++ .../trackers/service/Config.kt | 16 ++++ .../trackers/service/TrackersService.kt | 74 +++++-------------- .../service/TrackersServiceSupervisor.kt | 16 ++++ .../trackers/service/TunLooper.kt | 16 ++++ .../data/NetworkDNSAddressRepository.kt | 16 ++++ .../service/data/RequestDNSRepository.kt | 18 ++++- .../service/usecases/ResolveDNSUseCase.kt | 16 ++++ 19 files changed, 197 insertions(+), 80 deletions(-) diff --git a/.idea/vcs.xml b/.idea/vcs.xml index b3ceaf3f..94a25f7f 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c23b0591..fac1f753 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - Advanced Privacy_6 + Advanced Privacy Close diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt index d80cdf57..afaebf64 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt @@ -1,3 +1,19 @@ +/* + * 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.domain.entities enum class ServiceState { diff --git a/ipscrambling/build.gradle b/ipscrambling/build.gradle index b99f9c17..39efce74 100644 --- a/ipscrambling/build.gradle +++ b/ipscrambling/build.gradle @@ -52,5 +52,5 @@ dependencies { libs.androidx.localbroadcast, ) implementation libs.e.orbotservice -// implementation project(':ipscrambling:orbotservice') + //implementation project(':ipscrambling:orbotservice') } diff --git a/settings.gradle b/settings.gradle index f0b781df..bd6e8dc6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,7 +18,7 @@ include ':trackers' include ':permissionse' include ':permissionse:libs:hidden-apis-stub' include ':ipscrambling' -include ':ipscrambling:orbotservice' +//include ':ipscrambling:orbotservice' include ':trackersservicestandalone' include ':trackersservicee' diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt index 159f1ce1..47832c1c 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt @@ -1,3 +1,19 @@ +/* + * 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 ITrackersServiceSupervisor { 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 index 77171600..80cb0f6a 100644 --- 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 @@ -1,3 +1,19 @@ +/* + * 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 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 a6753db7..e7a84b8f 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 @@ -28,17 +28,6 @@ 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 -> - // Log.d("epic18", "logAccess: trackerId: $trackerId, appUid: $appUid, blocked: $blocked") - // database.logAccess(trackerId, app.apId, blocked) - // _newDataAvailable.emit(Unit) - // } - // } - fun getTrackersCallsOnPeriod( periodsCount: Int, periodUnit: TemporalUnit diff --git a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/DNSBlocker.kt b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/DNSBlocker.kt index ead3dbd8..6a2b2189 100644 --- a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/DNSBlocker.kt +++ b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/DNSBlocker.kt @@ -76,7 +76,7 @@ class DNSBlocker( Timber.d("DNSFilterProxy running on port $SOCKET_NAME") while (isActive) { - runCatching { + runSuspendCatching { val socket = resolverReceiver.accept() val reader = BufferedReader(InputStreamReader(socket.inputStream)) val line = reader.readLine() diff --git a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt index 55a69e2d..5f573b0f 100644 --- a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt +++ b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt @@ -28,8 +28,6 @@ import org.koin.java.KoinJavaComponent.get class TrackersService : 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" var coroutineScope = CoroutineScope(Dispatchers.IO) } @@ -40,9 +38,6 @@ class TrackersService : Service() { 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() } diff --git a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt index 4506c4de..b70e5f01 100644 --- a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt +++ b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt @@ -1,3 +1,19 @@ +/* + * 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.service import android.content.Context diff --git a/trackersservicestandalone/src/main/AndroidManifest.xml b/trackersservicestandalone/src/main/AndroidManifest.xml index 0047c165..4bfa4eb0 100644 --- a/trackersservicestandalone/src/main/AndroidManifest.xml +++ b/trackersservicestandalone/src/main/AndroidManifest.xml @@ -1,4 +1,20 @@ + diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt index bf71355c..f91b1d97 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt @@ -1,3 +1,19 @@ +/* + * 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.service internal object Config { diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt index e91dfe26..3323aef8 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt @@ -1,3 +1,19 @@ +/* + * 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.service import android.app.Notification @@ -87,74 +103,18 @@ class TrackersService : VpnService() { } // TODO: block private DNS. + // TODO 20230821: seen in privateDNSFilter, bypass filter for google apps on Android 7/8 - // this app itself should bypass VPN in order to prevent endless recursion builder.addDisallowedApplication(packageName) - - // TODO 20230821: seens in privateDNSFilter : -// // Android 7/8 has an issue with VPN in combination with some google apps - bypass the filter -// if (Build.VERSION.SDK_INT >= 24 && Build.VERSION.SDK_INT <= 27) { // Android 7/8 -// if (explicitOp) Logger.getLogger().logLine("Running on SDK" + Build.VERSION.SDK_INT) -// excludeApp("com.android.vending", builder) //white list play store -// excludeApp("com.google.android.apps.docs", builder) //white list google drive -// excludeApp("com.google.android.apps.photos", builder) //white list google photos -// excludeApp("com.google.android.gm", builder) //white list gmail -// excludeApp("com.google.android.apps.translate", builder) //white list google translate -// } - builder.setBlocking(true) - builder.setMtu(Config.MTU) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { builder.setMetered(false) // take over defaults from underlying network } - // Set the PendingIntent to an activity for users to configure the VPN connection. If it is not set, the button to configure will not be shown in system-managed dialogs. -// return builder.setConfigureIntent(pendingIntent).establish() - return builder.establish() } - // registerNEtworkCallback . - - // private fun getDNSviaConnectivityManager(): Array { - // val result = HashSet() - // val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager - // var networks: Array? = getConnectedNetworks( - // connectivityManager, - // ConnectivityManager.TYPE_WIFI - // ) // prefer WiFi - // - // if (networks?.size == 0) networks = getConnectedNetworks( - // connectivityManager, - // -1 - // ) // fallback all networks - // - // networks?.forEach { network -> - // val linkProperties = connectivityManager.getLinkProperties(network) - // if (linkProperties != null) { - // val dnsList = linkProperties.dnsServers - // for (i in dnsList.indices) { - // val adr = dnsList[i].hostAddress - // if (adr != Config.VIRTUALDNS_IPV4 && adr != Config.VIRTUALDNS_IPV6) result.add( - // adr - // ) - // } - // } else Timber.w("Cannot get link properties for $network") - // } - // return result.toTypedArray() - // } - // - // private fun getConnectedNetworks(conMan: ConnectivityManager, type: Int): Array { - // val nwList = ArrayList() - // val nw = conMan.allNetworks - // for (i in nw.indices) { - // val ni = conMan.getNetworkInfo(nw[i]) - // if (ni != null && (ni.type == type || type == -1) && ni.isConnected) nwList.add(nw[i]) - // } - // return nwList.toTypedArray() - // } - private fun createNotification(notificationManager: NotificationManager): Notification { val channel = NotificationChannel("foreground", "ForegorundNotif", NotificationManager.IMPORTANCE_LOW) notificationManager.createNotificationChannel(channel) diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt index 6efd39f2..2a5e0db3 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt @@ -1,3 +1,19 @@ +/* + * 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.service import android.content.Context diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt index 20b7a501..c65b6697 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt @@ -1,3 +1,19 @@ +/* + * 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.service import android.os.ParcelFileDescriptor diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt index f34a508f..324eebd7 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt @@ -1,3 +1,19 @@ +/* + * 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.service.data import android.content.Context diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt index c8e72082..3e4e8a63 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt @@ -1,3 +1,19 @@ +/* + * 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.service.data import kotlinx.coroutines.Dispatchers @@ -11,8 +27,6 @@ import java.net.DatagramSocket class RequestDNSRepository { suspend fun processDNS(request: DatagramPacket): DnsPacket? = withContext(Dispatchers.IO) { - // val payload = dnsRequest.rawData - // var packet = DatagramPacket(payload, payload.size, dnsAddress, dnsPort) var response: DnsPacket? = null val datagramSocket = DatagramSocket() datagramSocket.send(request) diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt index 55809496..3b5c4264 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt @@ -1,3 +1,19 @@ +/* + * 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.service.usecases import foundation.e.advancedprivacy.trackers.domain.usecases.FilterHostnameUseCase -- GitLab From 233142131157b22615173ee6f39e3bdafb5b0f2b Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Fri, 29 Sep 2023 19:30:53 +0200 Subject: [PATCH 3/5] Fix review comments. --- .gitignore | 16 +--------- .idea/vcs.xml | 6 ---- .../e/advancedprivacy/KoinModule.kt | 12 ++++---- .../e/advancedprivacy/common/utils.kt | 22 -------------- .../usecases/IpScramblingStateUseCase.kt | 4 +-- .../domain/usecases/TrackersStateUseCase.kt | 8 ++--- ...ServiceState.kt => TrackerServiceState.kt} | 2 +- ...ule.kt => PermissionsPrivacyModuleBase.kt} | 2 +- .../fakelocationdemo/MainActivity.kt | 4 +-- ...ule.kt => PermissionsPrivacyModuleImpl.kt} | 4 +-- ...ule.kt => PermissionsPrivacyModuleImpl.kt} | 4 +-- ...rvisor.kt => TrackersServiceSupervisor.kt} | 2 +- .../domain/usecases/FilterHostnameUseCase.kt | 2 +- ...or.kt => TrackersServiceSupervisorImpl.kt} | 4 +-- .../trackers/service/TrackersService.kt | 14 ++++----- ...or.kt => TrackersServiceSupervisorImpl.kt} | 16 +++++----- .../trackers/service/TunLooper.kt | 18 +++++------ .../data/NetworkDNSAddressRepository.kt | 16 +++++----- .../service/data/RequestDNSRepository.kt | 30 +++++++++---------- .../service/usecases/ResolveDNSUseCase.kt | 17 ++++------- 20 files changed, 76 insertions(+), 127 deletions(-) delete mode 100644 .idea/vcs.xml delete mode 100644 app/src/main/java/foundation/e/advancedprivacy/common/utils.kt rename core/src/main/java/foundation/e/advancedprivacy/domain/entities/{ServiceState.kt => TrackerServiceState.kt} (95%) rename core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/{APermissionsPrivacyModule.kt => PermissionsPrivacyModuleBase.kt} (98%) rename permissionse/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/{PermissionsPrivacyModule.kt => PermissionsPrivacyModuleImpl.kt} (98%) rename permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/{PermissionsPrivacyModule.kt => PermissionsPrivacyModuleImpl.kt} (95%) rename trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/{ITrackersServiceSupervisor.kt => TrackersServiceSupervisor.kt} (95%) rename trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/{TrackersServiceSupervisor.kt => TrackersServiceSupervisorImpl.kt} (92%) rename trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/{TrackersServiceSupervisor.kt => TrackersServiceSupervisorImpl.kt} (79%) diff --git a/.gitignore b/.gitignore index 09d358cd..7d062062 100644 --- a/.gitignore +++ b/.gitignore @@ -6,21 +6,7 @@ build/ local.properties # IntelliJ .idea folder -/.idea/caches -/.idea/libraries -/.idea/misc.xml -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -.idea/tasks.xml -.idea/compiler.xml -/.idea/assetWizardSettings.xml -/.idea/jarRepositories.xml -/.idea/google-java-format.xml -/.idea/runConfigurations.xml -/.idea/dbnavigator.xml -/.idea/deploymentTargetDropDown.xml -/.idea/kotlinc.xml +.idea/ gradle.xml markdown-*.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt index d88edade..d88a4fb2 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt @@ -39,9 +39,9 @@ import foundation.e.advancedprivacy.features.location.FakeLocationViewModel import foundation.e.advancedprivacy.features.trackers.TrackersViewModel import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersViewModel import foundation.e.advancedprivacy.ipscrambler.ipScramblerModule -import foundation.e.advancedprivacy.permissions.externalinterfaces.PermissionsPrivacyModule -import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor -import foundation.e.advancedprivacy.trackers.service.TrackersServiceSupervisor +import foundation.e.advancedprivacy.permissions.externalinterfaces.PermissionsPrivacyModuleImpl +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.service.TrackersServiceSupervisorImpl import foundation.e.advancedprivacy.trackers.service.trackerServiceModule import foundation.e.advancedprivacy.trackers.trackersModule import org.koin.android.ext.koin.androidContext @@ -123,11 +123,11 @@ val appModule = module { singleOf(::TrackersStatisticsUseCase) single { - PermissionsPrivacyModule(context = androidContext()) + PermissionsPrivacyModuleImpl(context = androidContext()) } - single { - TrackersServiceSupervisor( + single { + TrackersServiceSupervisorImpl( context = androidContext(), ) } diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/utils.kt b/app/src/main/java/foundation/e/advancedprivacy/common/utils.kt deleted file mode 100644 index acd16ca3..00000000 --- a/app/src/main/java/foundation/e/advancedprivacy/common/utils.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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.common - -import foundation.e.advancedprivacy.BuildConfig - -val isStandaloneFlavor = BuildConfig.FLAVOR == "standalone" diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt index d733faea..d465a9d5 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt @@ -19,7 +19,7 @@ package foundation.e.advancedprivacy.domain.usecases import android.content.Intent -import foundation.e.advancedprivacy.common.isStandaloneFlavor +import foundation.e.advancedprivacy.BuildConfig import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription @@ -191,7 +191,7 @@ class IpScramblingStateUseCase( fun startIpScrambling() { localStateRepository.internetPrivacyMode.value = HIDE_IP_LOADING - ipScramblerModule.start(enableNotification = isStandaloneFlavor) + ipScramblerModule.start(enableNotification = BuildConfig.FLAVOR == "standalone") } private fun map(status: IpScramblerModule.Status): InternetPrivacyMode { diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt index 0fe0c52b..7410d8b1 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt @@ -17,13 +17,13 @@ package foundation.e.advancedprivacy.domain.usecases -import foundation.e.advancedprivacy.common.isStandaloneFlavor +import foundation.e.advancedprivacy.BuildConfig import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription import foundation.e.advancedprivacy.trackers.data.WhitelistRepository import foundation.e.advancedprivacy.trackers.domain.entities.Tracker -import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -31,7 +31,7 @@ class TrackersStateUseCase( private val whitelistRepository: WhitelistRepository, private val localStateRepository: LocalStateRepository, private val appListsRepository: AppListsRepository, - private val trackersServiceSupervisor: ITrackersServiceSupervisor, + private val trackersServiceSupervisor: TrackersServiceSupervisor, coroutineScope: CoroutineScope, ) { init { @@ -42,7 +42,7 @@ class TrackersStateUseCase( } } - if (isStandaloneFlavor) { + if (BuildConfig.FLAVOR == "standalone") { coroutineScope.launch { localStateRepository.blockTrackers.collect { enabled -> if (enabled) { diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/TrackerServiceState.kt similarity index 95% rename from core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt rename to core/src/main/java/foundation/e/advancedprivacy/domain/entities/TrackerServiceState.kt index afaebf64..40481c6d 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/ServiceState.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/TrackerServiceState.kt @@ -16,6 +16,6 @@ */ package foundation.e.advancedprivacy.domain.entities -enum class ServiceState { +enum class TrackerServiceState { OFF, ON, STARTING, STOPPING } diff --git a/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/APermissionsPrivacyModule.kt b/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleBase.kt similarity index 98% rename from core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/APermissionsPrivacyModule.kt rename to core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleBase.kt index 78f424b4..27ba17f5 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/APermissionsPrivacyModule.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleBase.kt @@ -37,7 +37,7 @@ import foundation.e.advancedprivacy.domain.entities.ProfileType * versions of the module. * @param context an Android context, to retrieve packageManager for example. */ -abstract class APermissionsPrivacyModule(protected val context: Context) : IPermissionsPrivacyModule { +abstract class PermissionsPrivacyModuleBase(protected val context: Context) : IPermissionsPrivacyModule { companion object { private const val TAG = "PermissionsModule" diff --git a/fakelocation/fakelocationdemo/src/main/java/foundation/e/privacymodules/fakelocationdemo/MainActivity.kt b/fakelocation/fakelocationdemo/src/main/java/foundation/e/privacymodules/fakelocationdemo/MainActivity.kt index f2e10a44..c105ceb0 100644 --- a/fakelocation/fakelocationdemo/src/main/java/foundation/e/privacymodules/fakelocationdemo/MainActivity.kt +++ b/fakelocation/fakelocationdemo/src/main/java/foundation/e/privacymodules/fakelocationdemo/MainActivity.kt @@ -37,7 +37,7 @@ import foundation.e.advancedprivacy.domain.entities.AppOpModes import foundation.e.advancedprivacy.domain.entities.ApplicationDescription import foundation.e.advancedprivacy.domain.entities.ProfileType import foundation.e.advancedprivacy.fakelocation.domain.usecases.FakeLocationModule -import foundation.e.advancedprivacy.permissions.externalinterfaces.PermissionsPrivacyModule +import foundation.e.advancedprivacy.permissions.externalinterfaces.PermissionsPrivacyModuleImpl import foundation.e.privacymodules.fakelocationdemo.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { @@ -46,7 +46,7 @@ class MainActivity : AppCompatActivity() { } private val fakeLocationModule: FakeLocationModule by lazy { FakeLocationModule(this) } - private val permissionsModule by lazy { PermissionsPrivacyModule(this) } + private val permissionsModule by lazy { PermissionsPrivacyModuleImpl(this) } private lateinit var binding: ActivityMainBinding diff --git a/permissionse/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModule.kt b/permissionse/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleImpl.kt similarity index 98% rename from permissionse/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModule.kt rename to permissionse/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleImpl.kt index 59a20dd7..0d32bce6 100644 --- a/permissionse/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModule.kt +++ b/permissionse/src/main/java/foundation/e/advancedprivacy/externalinterfaces/permissions/PermissionsPrivacyModuleImpl.kt @@ -39,12 +39,12 @@ import foundation.e.advancedprivacy.domain.entities.AppOpModes import foundation.e.advancedprivacy.domain.entities.ApplicationDescription import foundation.e.advancedprivacy.domain.entities.ProfileType.MAIN import foundation.e.advancedprivacy.domain.entities.ProfileType.WORK -import foundation.e.advancedprivacy.externalinterfaces.permissions.APermissionsPrivacyModule +import foundation.e.advancedprivacy.externalinterfaces.permissions.PermissionsPrivacyModuleBase /** * Implements [IPermissionsPrivacyModule] with all privileges of a system app. */ -class PermissionsPrivacyModule(context: Context) : APermissionsPrivacyModule(context) { +class PermissionsPrivacyModuleImpl(context: Context) : PermissionsPrivacyModuleBase(context) { private val appOpsManager: AppOpsManager get() = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager diff --git a/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModule.kt b/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModuleImpl.kt similarity index 95% rename from permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModule.kt rename to permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModuleImpl.kt index 95f5ff09..d31bdf44 100644 --- a/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModule.kt +++ b/permissionsstandalone/src/main/java/foundation/e/advancedprivacy/permissions/externalinterfaces/PermissionsPrivacyModuleImpl.kt @@ -24,12 +24,12 @@ import android.content.pm.PackageManager import android.graphics.drawable.Drawable import foundation.e.advancedprivacy.domain.entities.AppOpModes import foundation.e.advancedprivacy.domain.entities.ApplicationDescription -import foundation.e.advancedprivacy.externalinterfaces.permissions.APermissionsPrivacyModule +import foundation.e.advancedprivacy.externalinterfaces.permissions.PermissionsPrivacyModuleBase /** * Implements [IPermissionsPrivacyModule] using only API authorized on the PlayStore. */ -class PermissionsPrivacyModule(context: Context) : APermissionsPrivacyModule(context) { +class PermissionsPrivacyModuleImpl(context: Context) : PermissionsPrivacyModuleBase(context) { override fun getApplications( filter: ((PackageInfo) -> Boolean)? ): List { diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/TrackersServiceSupervisor.kt similarity index 95% rename from trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt rename to trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/TrackersServiceSupervisor.kt index 47832c1c..d9674fc9 100644 --- a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/ITrackersServiceSupervisor.kt +++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/externalinterfaces/TrackersServiceSupervisor.kt @@ -16,7 +16,7 @@ */ package foundation.e.advancedprivacy.trackers.domain.externalinterfaces -interface ITrackersServiceSupervisor { +interface TrackersServiceSupervisor { fun start(): Boolean fun stop(): Boolean fun isRunning(): Boolean 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 index 80cb0f6a..56582866 100644 --- 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 @@ -39,7 +39,7 @@ class FilterHostnameUseCase( context: Context, private val appDesc: ApplicationDescription, private val database: StatsDatabase, - private val appListsRepository: AppListsRepository + private val appListsRepository: AppListsRepository, ) { private var eBrowserAppUid = -1 diff --git a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt similarity index 92% rename from trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt rename to trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt index b70e5f01..3903db48 100644 --- a/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt +++ b/trackersservicee/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt @@ -18,13 +18,13 @@ package foundation.e.advancedprivacy.trackers.service import android.content.Context import android.content.Intent -import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor import foundation.e.advancedprivacy.trackers.service.TrackersService.Companion.ACTION_START import kotlinx.coroutines.isActive import org.koin.core.module.dsl.factoryOf import org.koin.dsl.module -class TrackersServiceSupervisor(private val context: Context) : ITrackersServiceSupervisor { +class TrackersServiceSupervisorImpl(private val context: Context) : TrackersServiceSupervisor { override fun start(): Boolean { val intent = Intent(context, TrackersService::class.java) diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt index 3323aef8..f17cd3ce 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt @@ -24,8 +24,8 @@ import android.content.Intent import android.net.VpnService import android.os.Build import android.os.ParcelFileDescriptor -import foundation.e.advancedprivacy.domain.entities.ServiceState -import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.domain.entities.TrackerServiceState +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor import foundation.e.advancedprivacy.trackers.service.Config.DNS_SERVER_TO_CATCH_IPV4 import foundation.e.advancedprivacy.trackers.service.Config.DNS_SERVER_TO_CATCH_IPV6 import foundation.e.advancedprivacy.trackers.service.Config.SESSION_NAME @@ -47,23 +47,23 @@ class TrackersService : VpnService() { } private val networkDNSAddressRepository: NetworkDNSAddressRepository = get(NetworkDNSAddressRepository::class.java) - private val trackersServiceSupervisor: TrackersServiceSupervisor = get( - ITrackersServiceSupervisor::class.java - ) as TrackersServiceSupervisor + private val trackersServiceSupervisor: TrackersServiceSupervisorImpl = get( + TrackersServiceSupervisor::class.java + ) as TrackersServiceSupervisorImpl override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { startVPN() startForeground(1, createNotification(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)) - trackersServiceSupervisor.state.value = ServiceState.ON + trackersServiceSupervisor.state.value = TrackerServiceState.ON return START_STICKY } override fun onDestroy() { networkDNSAddressRepository.stop() - trackersServiceSupervisor.state.value = ServiceState.OFF + trackersServiceSupervisor.state.value = TrackerServiceState.OFF super.onDestroy() } diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt similarity index 79% rename from trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt rename to trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt index 2a5e0db3..1bc3694a 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisor.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt @@ -18,8 +18,8 @@ package foundation.e.advancedprivacy.trackers.service import android.content.Context import android.content.Intent -import foundation.e.advancedprivacy.domain.entities.ServiceState -import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.ITrackersServiceSupervisor +import foundation.e.advancedprivacy.domain.entities.TrackerServiceState +import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor import foundation.e.advancedprivacy.trackers.service.data.NetworkDNSAddressRepository import foundation.e.advancedprivacy.trackers.service.data.RequestDNSRepository import foundation.e.advancedprivacy.trackers.service.usecases.ResolveDNSUseCase @@ -28,12 +28,12 @@ import kotlinx.coroutines.flow.MutableStateFlow import org.koin.core.module.dsl.singleOf import org.koin.dsl.module -class TrackersServiceSupervisor(private val context: Context) : ITrackersServiceSupervisor { - internal val state: MutableStateFlow = MutableStateFlow(ServiceState.OFF) +class TrackersServiceSupervisorImpl(private val context: Context) : TrackersServiceSupervisor { + internal val state: MutableStateFlow = MutableStateFlow(TrackerServiceState.OFF) override fun start(): Boolean { return if (!isRunning()) { - state.value = ServiceState.STARTING + state.value = TrackerServiceState.STARTING TrackersService.start(context) true } else false @@ -41,8 +41,8 @@ class TrackersServiceSupervisor(private val context: Context) : ITrackersService override fun stop(): Boolean { return when (state.value) { - ServiceState.ON -> { - state.value = ServiceState.STOPPING + TrackerServiceState.ON -> { + state.value = TrackerServiceState.STOPPING kotlin.runCatching { TrackersService.coroutineScope.cancel() } context.stopService(Intent(context, TrackersService::class.java)) true @@ -52,7 +52,7 @@ class TrackersServiceSupervisor(private val context: Context) : ITrackersService } override fun isRunning(): Boolean { - return state.value != ServiceState.OFF + return state.value != TrackerServiceState.OFF } } diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt index c65b6697..c1bb30e6 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt @@ -44,15 +44,15 @@ class TunLooper( private val resolveDNSUseCase: ResolveDNSUseCase, ) { private var vpnInterface: ParcelFileDescriptor? = null - private var fis: FileInputStream? = null - private var fos: DataOutputStream? = null + private var fileInputStream: FileInputStream? = null + private var dataOutputStream: DataOutputStream? = null private fun closeStreams() { - fis?.close() - fis = null + fileInputStream?.close() + fileInputStream = null - fos?.close() - fos = null + dataOutputStream?.close() + dataOutputStream = null vpnInterface?.close() vpnInterface = null @@ -64,8 +64,8 @@ class TunLooper( ): Job = scope.launch(Dispatchers.IO) { this@TunLooper.vpnInterface = vpnInterface val fis = FileInputStream(vpnInterface.fileDescriptor) - this@TunLooper.fis = fis - fos = DataOutputStream(FileOutputStream(vpnInterface.fileDescriptor)) + this@TunLooper.fileInputStream = fis + dataOutputStream = DataOutputStream(FileOutputStream(vpnInterface.fileDescriptor)) while (isActive) { runCatching { @@ -151,7 +151,7 @@ class TunLooper( respPacket?.let { try { - fos?.write(it.rawData) + dataOutputStream?.write(it.rawData) } catch (e: IOException) { Timber.e("error writing to VPN fd", e) } diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt index 324eebd7..7c36ed2e 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/NetworkDNSAddressRepository.kt @@ -21,12 +21,12 @@ import android.net.ConnectivityManager import android.net.Network import android.net.NetworkRequest import foundation.e.advancedprivacy.trackers.service.Config -import timber.log.Timber import java.net.InetAddress class NetworkDNSAddressRepository(private val context: Context) { private val connectivityManager: ConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + fun start() { connectivityManager.registerNetworkCallback( NetworkRequest.Builder().build(), @@ -46,16 +46,14 @@ class NetworkDNSAddressRepository(private val context: Context) { private val networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { super.onAvailable(network) - val linkProperties = connectivityManager.getLinkProperties(network) - if (linkProperties != null) { - val dnsList = linkProperties.dnsServers - for (i in dnsList.indices) { - val adr = dnsList[i].hostAddress - if (adr != Config.VIRTUALDNS_IPV4 && adr != Config.VIRTUALDNS_IPV6) { - dnsAddress = InetAddress.getByName(adr) + connectivityManager.getLinkProperties(network) + ?.dnsServers?.firstOrNull { + it.hostAddress.let { + it != Config.VIRTUALDNS_IPV4 && it != Config.VIRTUALDNS_IPV6 } + }?.let { + dnsAddress = InetAddress.getByName(it.hostAddress) } - } else Timber.w("Cannot get link properties for $network") } } } diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt index 3e4e8a63..d9370be5 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/data/RequestDNSRepository.kt @@ -16,10 +16,10 @@ */ package foundation.e.advancedprivacy.trackers.service.data +import foundation.e.advancedprivacy.core.utils.runSuspendCatching import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.pcap4j.packet.DnsPacket -import org.pcap4j.packet.IllegalRawDataException import timber.log.Timber import java.net.DatagramPacket import java.net.DatagramSocket @@ -27,22 +27,22 @@ import java.net.DatagramSocket class RequestDNSRepository { suspend fun processDNS(request: DatagramPacket): DnsPacket? = withContext(Dispatchers.IO) { - var response: DnsPacket? = null - val datagramSocket = DatagramSocket() - datagramSocket.send(request) + runSuspendCatching { + var response: DnsPacket? = null + val datagramSocket = DatagramSocket() + datagramSocket.send(request) - // Await response from DNS server - val buf = ByteArray(1024) - val packet = DatagramPacket(buf, buf.size) - datagramSocket.receive(packet) - val dnsResp = packet.data - if (dnsResp != null) { - try { + // Await response from DNS server + val buf = ByteArray(1024) + val packet = DatagramPacket(buf, buf.size) + datagramSocket.receive(packet) + val dnsResp = packet.data + if (dnsResp != null) { response = DnsPacket.newPacket(dnsResp, 0, dnsResp.size) - } catch (e: IllegalRawDataException) { - Timber.e("Can't parse DNS response", e) } - } - response + response + }.onFailure { + Timber.w(it, "Can't make DNS request.") + }.getOrNull() } } diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt index 3b5c4264..ac8aee03 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/usecases/ResolveDNSUseCase.kt @@ -24,8 +24,6 @@ import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import org.pcap4j.packet.DnsPacket import org.pcap4j.packet.namednumber.DnsRCode -import timber.log.Timber -import java.io.IOException import java.net.DatagramPacket @OptIn(DelicateCoroutinesApi::class) @@ -41,17 +39,12 @@ class ResolveDNSUseCase( filterHostnameUseCase.writeLogJob(scope) } - @Throws(IOException::class) suspend fun processDNS(dnsRequest: DnsPacket): DnsPacket? { - try { - val host = dnsRequest.header.questions[0].qName.name - if (filterHostnameUseCase.shouldBlock(host)) { - return dnsRequest.builder - .rCode(DnsRCode.NX_DOMAIN) - .response(true).build() - } - } catch (e: Exception) { - Timber.e("Can't find host", e) + val host = dnsRequest.header.questions[0].qName.name + if (filterHostnameUseCase.shouldBlock(host)) { + return dnsRequest.builder + .rCode(DnsRCode.NX_DOMAIN) + .response(true).build() } val payload = dnsRequest.rawData -- GitLab From 3b5698f971c8789f22f557693286ddcc33c0b0ac Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Tue, 3 Oct 2023 22:56:52 +0200 Subject: [PATCH 4/5] Review fixes 2. --- app/build.gradle | 1 + .../e/advancedprivacy/KoinModule.kt | 12 ++++ .../e/advancedprivacy/Notifications.kt | 56 +++++++++---------- .../e/advancedprivacy/common/BuildFlavor.kt | 5 ++ .../e/advancedprivacy/common/WarningDialog.kt | 2 +- .../usecases/FakeLocationStateUseCase.kt | 2 +- .../usecases/IpScramblingStateUseCase.kt | 4 +- .../domain/usecases/TrackersStateUseCase.kt | 16 +----- app/src/main/res/values/strings.xml | 5 ++ .../core/utils/NotificationsHelper.kt | 19 +++++++ ...ServiceState.kt => FeatureServiceState.kt} | 2 +- .../domain/entities/NotificationChannels.kt | 11 ++++ .../domain/entities/NotificationContent.kt | 11 ++++ settings.gradle | 1 - .../data/RemoteTrackersListRepository.kt | 2 +- .../trackers/data/TrackersRepository.kt | 2 +- .../domain/usecases/FilterHostnameUseCase.kt | 2 - .../usecases/UpdateTrackerListUseCase.kt | 2 +- .../trackers/service/Config.kt | 1 - .../trackers/service/TrackersService.kt | 33 ++++++----- .../service/TrackersServiceSupervisorImpl.kt | 12 ++-- .../trackers/service/TunLooper.kt | 4 +- 22 files changed, 123 insertions(+), 82 deletions(-) create mode 100644 app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt create mode 100644 core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt rename core/src/main/java/foundation/e/advancedprivacy/domain/entities/{TrackerServiceState.kt => FeatureServiceState.kt} (95%) create mode 100644 core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt create mode 100644 core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt diff --git a/app/build.gradle b/app/build.gradle index 8a64d6d0..216b81af 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,6 +97,7 @@ android { persistent: "false", mainActivityIntentFilterCategory: "android.intent.category.LAUNCHER" ] + signingConfig signingConfigs.debug } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt index d88a4fb2..20cefd50 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt @@ -22,6 +22,8 @@ import android.os.Process import foundation.e.advancedprivacy.core.coreModule import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription +import foundation.e.advancedprivacy.domain.entities.CHANNEL_TRACKER_FLAG +import foundation.e.advancedprivacy.domain.entities.NotificationContent import foundation.e.advancedprivacy.domain.entities.ProfileType import foundation.e.advancedprivacy.domain.usecases.AppListUseCase import foundation.e.advancedprivacy.domain.usecases.FakeLocationStateUseCase @@ -92,6 +94,16 @@ val appModule = module { ) } + single(named("notificationTrackerFlag")) { + NotificationContent( + channelId = CHANNEL_TRACKER_FLAG, + icon = R.drawable.ic_e_app_logo, + title = R.string.notifications_tracker_title, + description = R.string.notifications_tracker_content, + pendingIntent = null + ) + } + single { CityDataSource } singleOf(::AppListUseCase) diff --git a/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt index cd85e9a6..10bcd49a 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt @@ -20,13 +20,21 @@ package foundation.e.advancedprivacy import android.app.NotificationChannel import android.app.NotificationManager -import android.app.PendingIntent import android.content.Context import androidx.annotation.StringRes import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat +import foundation.e.advancedprivacy.core.utils.notificationBuilder +import foundation.e.advancedprivacy.domain.entities.CHANNEL_FAKE_LOCATION_FLAG +import foundation.e.advancedprivacy.domain.entities.CHANNEL_FIRST_BOOT +import foundation.e.advancedprivacy.domain.entities.CHANNEL_IPSCRAMBLING_FLAG +import foundation.e.advancedprivacy.domain.entities.CHANNEL_TRACKER_FLAG import foundation.e.advancedprivacy.domain.entities.InternetPrivacyMode import foundation.e.advancedprivacy.domain.entities.MainFeatures +import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FAKE_LOCATION_FLAG +import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FIRST_BOOT +import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_IPSCRAMBLING_FLAG +import foundation.e.advancedprivacy.domain.entities.NotificationContent import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule import foundation.e.advancedprivacy.main.MainActivity @@ -37,13 +45,15 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach object Notifications { - const val CHANNEL_FIRST_BOOT = "first_boot_notification" - const val CHANNEL_FAKE_LOCATION_FLAG = "fake_location_flag" - const val CHANNEL_IPSCRAMBLING_FLAG = "ipscrambling_flag" - - const val NOTIFICATION_FIRST_BOOT = 1000 - const val NOTIFICATION_FAKE_LOCATION_FLAG = NOTIFICATION_FIRST_BOOT + 1 - const val NOTIFICATION_IPSCRAMBLING_FLAG = NOTIFICATION_FAKE_LOCATION_FLAG + 1 + // const val CHANNEL_FIRST_BOOT = "first_boot_notification" + // const val CHANNEL_FAKE_LOCATION_FLAG = "fake_location_flag" + // const val CHANNEL_IPSCRAMBLING_FLAG = "ipscrambling_flag" + // const val CHANNEL_TRACKER_FLAG = "tracker_flag" + // + // const val NOTIFICATION_FIRST_BOOT = 1000 + // const val NOTIFICATION_FAKE_LOCATION_FLAG = NOTIFICATION_FIRST_BOOT + 1 + // const val NOTIFICATION_IPSCRAMBLING_FLAG = NOTIFICATION_FAKE_LOCATION_FLAG + 1 + // const val NOTIFICATION_TRACKER_FLAG = NOTIFICATION_IPSCRAMBLING_FLAG + 1 fun showFirstBootNotification(context: Context) { createNotificationFirstBootChannel(context) @@ -88,6 +98,14 @@ object Notifications { channelDescription = R.string.notifications_ipscrambling_channel_description ) + createNotificationFlagChannel( + context = appContext, + permissionsPrivacyModule = permissionsPrivacyModule, + channelId = CHANNEL_TRACKER_FLAG, + channelName = R.string.notifications_tracker_channel_name, + channelDescription = R.string.notifications_ipscrambling_channel_description + ) + getQuickPrivacyStateUseCase.isLocationHidden.onEach { if (it) { showFlagNotification(appContext, MainFeatures.FAKE_LOCATION) @@ -183,26 +201,4 @@ object Notifications { } NotificationManagerCompat.from(context).cancel(id) } - - private data class NotificationContent( - val channelId: String, - val icon: Int, - val title: Int, - val description: Int, - val pendingIntent: PendingIntent? - ) - - private fun notificationBuilder( - context: Context, - content: NotificationContent - ): NotificationCompat.Builder { - val builder = NotificationCompat.Builder(context, content.channelId) - .setSmallIcon(content.icon) - .setPriority(NotificationCompat.PRIORITY_LOW) - .setContentTitle(context.getString(content.title)) - .setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(content.description))) - content.pendingIntent?.let { builder.setContentIntent(it) } - - return builder - } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt b/app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt new file mode 100644 index 00000000..0afa381f --- /dev/null +++ b/app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt @@ -0,0 +1,5 @@ +package foundation.e.advancedprivacy.common.extensions + +import foundation.e.advancedprivacy.BuildConfig + +val isStandaloneBuild: Boolean = BuildConfig.FLAVOR == "standalone" diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/WarningDialog.kt b/app/src/main/java/foundation/e/advancedprivacy/common/WarningDialog.kt index 80fc7601..589aa74f 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/common/WarningDialog.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/common/WarningDialog.kt @@ -75,7 +75,7 @@ class WarningDialog : AppCompatActivity() { val feature = try { intent.getParcelableExtra(PARAM_FEATURE)!! } catch (e: Exception) { - Timber.e("Missing mandatory activity parameter", e) + Timber.e(e, "Missing mandatory activity parameter") finish() return } diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt index 30c8e6ba..983ba714 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt @@ -202,7 +202,7 @@ class FakeLocationStateUseCase( lastKnownLocation?.let { localListener.onLocationChanged(it) } } catch (se: SecurityException) { - Timber.e("Missing permission", se) + Timber.e(se, "Missing permission") } } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt index d465a9d5..ec61b408 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt @@ -19,7 +19,7 @@ package foundation.e.advancedprivacy.domain.usecases import android.content.Intent -import foundation.e.advancedprivacy.BuildConfig +import foundation.e.advancedprivacy.common.extensions.isStandaloneBuild import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription @@ -191,7 +191,7 @@ class IpScramblingStateUseCase( fun startIpScrambling() { localStateRepository.internetPrivacyMode.value = HIDE_IP_LOADING - ipScramblerModule.start(enableNotification = BuildConfig.FLAVOR == "standalone") + ipScramblerModule.start(enableNotification = isStandaloneBuild) } private fun map(status: IpScramblerModule.Status): InternetPrivacyMode { diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt index 7410d8b1..9b79dcc1 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/TrackersStateUseCase.kt @@ -17,7 +17,6 @@ package foundation.e.advancedprivacy.domain.usecases -import foundation.e.advancedprivacy.BuildConfig import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription @@ -42,20 +41,7 @@ class TrackersStateUseCase( } } - if (BuildConfig.FLAVOR == "standalone") { - coroutineScope.launch { - localStateRepository.blockTrackers.collect { enabled -> - if (enabled) { - // TODO: VPnService intent handling permission. - trackersServiceSupervisor.start() - } else { - trackersServiceSupervisor.stop() - } - } - } - } else { - trackersServiceSupervisor.start() - } + trackersServiceSupervisor.start() } private fun updateAllTrackersBlockedState() { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fac1f753..ba3ba03e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -144,4 +144,9 @@ Real IP hidden This could impact the functioning of some applications. + Tracker control flag + Highlight that the trackers are actually logged and blocked by Advanced Privacy + Tracker control is on + This could impact the functioning of some applications. + diff --git a/core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt b/core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt new file mode 100644 index 00000000..3e388570 --- /dev/null +++ b/core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt @@ -0,0 +1,19 @@ +package foundation.e.advancedprivacy.core.utils + +import android.content.Context +import androidx.core.app.NotificationCompat +import foundation.e.advancedprivacy.domain.entities.NotificationContent + +fun notificationBuilder( + context: Context, + content: NotificationContent +): NotificationCompat.Builder { + val builder = NotificationCompat.Builder(context, content.channelId) + .setSmallIcon(content.icon) + .setPriority(NotificationCompat.PRIORITY_LOW) + .setContentTitle(context.getString(content.title)) + .setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(content.description))) + content.pendingIntent?.let { builder.setContentIntent(it) } + + return builder +} diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/TrackerServiceState.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/FeatureServiceState.kt similarity index 95% rename from core/src/main/java/foundation/e/advancedprivacy/domain/entities/TrackerServiceState.kt rename to core/src/main/java/foundation/e/advancedprivacy/domain/entities/FeatureServiceState.kt index 40481c6d..6bfecbb9 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/TrackerServiceState.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/FeatureServiceState.kt @@ -16,6 +16,6 @@ */ package foundation.e.advancedprivacy.domain.entities -enum class TrackerServiceState { +enum class FeatureServiceState { OFF, ON, STARTING, STOPPING } diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt new file mode 100644 index 00000000..7b01ac0f --- /dev/null +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt @@ -0,0 +1,11 @@ +package foundation.e.advancedprivacy.domain.entities + +const val CHANNEL_FIRST_BOOT = "first_boot_notification" +const val CHANNEL_FAKE_LOCATION_FLAG = "fake_location_flag" +const val CHANNEL_IPSCRAMBLING_FLAG = "ipscrambling_flag" +const val CHANNEL_TRACKER_FLAG = "tracker_flag" + +const val NOTIFICATION_FIRST_BOOT = 1000 +const val NOTIFICATION_FAKE_LOCATION_FLAG = NOTIFICATION_FIRST_BOOT + 1 +const val NOTIFICATION_IPSCRAMBLING_FLAG = NOTIFICATION_FAKE_LOCATION_FLAG + 1 +const val NOTIFICATION_TRACKER_FLAG = NOTIFICATION_IPSCRAMBLING_FLAG + 1 diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt new file mode 100644 index 00000000..04055ee8 --- /dev/null +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt @@ -0,0 +1,11 @@ +package foundation.e.advancedprivacy.domain.entities + +import android.app.PendingIntent + +data class NotificationContent( + val channelId: String, + val icon: Int, + val title: Int, + val description: Int, + val pendingIntent: PendingIntent? +) diff --git a/settings.gradle b/settings.gradle index bd6e8dc6..39e58c8d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,7 +18,6 @@ include ':trackers' include ':permissionse' include ':permissionse:libs:hidden-apis-stub' include ':ipscrambling' -//include ':ipscrambling:orbotservice' include ':trackersservicestandalone' include ':trackersservicee' 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 c2c0768e..64477b7e 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/TrackersRepository.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt index a7d5e49d..fc57a8ef 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/usecases/FilterHostnameUseCase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/FilterHostnameUseCase.kt index 56582866..e229cab9 100644 --- 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 @@ -18,7 +18,6 @@ package foundation.e.advancedprivacy.trackers.domain.usecases import android.content.Context import android.content.pm.PackageManager -import android.util.Log import foundation.e.advancedprivacy.core.utils.runSuspendCatching import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription @@ -52,7 +51,6 @@ class FilterHostnameUseCase( } fun shouldBlock(hostname: String, appUid: Int = appDesc.uid): Boolean { - Log.d("epic18", "shouldblock: $hostname, appUid: $appUid") var isBlocked = false if (isEBrowserDoTBlockFix(appUid, hostname)) { 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 55da6449..fa60431c 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/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt index f91b1d97..d079e22e 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/Config.kt @@ -33,7 +33,6 @@ internal object Config { const val MTU = 3000 const val LOCAL_RESOLVER_TTL = 60 - // const val MAX_RESOLVER_COUNT = 100 val DNS_SERVER_TO_CATCH_IPV4 = listOf( diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt index f17cd3ce..28889a39 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt @@ -16,15 +16,15 @@ */ package foundation.e.advancedprivacy.trackers.service -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager import android.content.Context import android.content.Intent import android.net.VpnService import android.os.Build import android.os.ParcelFileDescriptor -import foundation.e.advancedprivacy.domain.entities.TrackerServiceState +import foundation.e.advancedprivacy.core.utils.notificationBuilder +import foundation.e.advancedprivacy.domain.entities.FeatureServiceState +import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_TRACKER_FLAG +import foundation.e.advancedprivacy.domain.entities.NotificationContent import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor import foundation.e.advancedprivacy.trackers.service.Config.DNS_SERVER_TO_CATCH_IPV4 import foundation.e.advancedprivacy.trackers.service.Config.DNS_SERVER_TO_CATCH_IPV6 @@ -32,6 +32,7 @@ import foundation.e.advancedprivacy.trackers.service.Config.SESSION_NAME import foundation.e.advancedprivacy.trackers.service.data.NetworkDNSAddressRepository import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import org.koin.core.qualifier.named import org.koin.java.KoinJavaComponent.get import timber.log.Timber @@ -51,19 +52,26 @@ class TrackersService : VpnService() { TrackersServiceSupervisor::class.java ) as TrackersServiceSupervisorImpl + private val notificationTrackerFlag: NotificationContent = get(NotificationContent::class.java, named("notificationTrackerFlag")) + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { startVPN() - startForeground(1, createNotification(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)) - - trackersServiceSupervisor.state.value = TrackerServiceState.ON + startForeground( + NOTIFICATION_TRACKER_FLAG, + notificationBuilder( + context = this, + content = notificationTrackerFlag + ).build() + ) + trackersServiceSupervisor.state.value = FeatureServiceState.ON return START_STICKY } override fun onDestroy() { networkDNSAddressRepository.stop() - trackersServiceSupervisor.state.value = TrackerServiceState.OFF + trackersServiceSupervisor.state.value = FeatureServiceState.OFF super.onDestroy() } @@ -114,13 +122,4 @@ class TrackersService : VpnService() { return builder.establish() } - - private fun createNotification(notificationManager: NotificationManager): Notification { - val channel = NotificationChannel("foreground", "ForegorundNotif", NotificationManager.IMPORTANCE_LOW) - notificationManager.createNotificationChannel(channel) - return Notification.Builder(this, "foreground") - .setContentTitle("TunProxyVpnService") - .setContentText("Running") - .build() - } } diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt index 1bc3694a..25d3e2d4 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersServiceSupervisorImpl.kt @@ -18,7 +18,7 @@ package foundation.e.advancedprivacy.trackers.service import android.content.Context import android.content.Intent -import foundation.e.advancedprivacy.domain.entities.TrackerServiceState +import foundation.e.advancedprivacy.domain.entities.FeatureServiceState import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor import foundation.e.advancedprivacy.trackers.service.data.NetworkDNSAddressRepository import foundation.e.advancedprivacy.trackers.service.data.RequestDNSRepository @@ -29,11 +29,11 @@ import org.koin.core.module.dsl.singleOf import org.koin.dsl.module class TrackersServiceSupervisorImpl(private val context: Context) : TrackersServiceSupervisor { - internal val state: MutableStateFlow = MutableStateFlow(TrackerServiceState.OFF) + internal val state: MutableStateFlow = MutableStateFlow(FeatureServiceState.OFF) override fun start(): Boolean { return if (!isRunning()) { - state.value = TrackerServiceState.STARTING + state.value = FeatureServiceState.STARTING TrackersService.start(context) true } else false @@ -41,8 +41,8 @@ class TrackersServiceSupervisorImpl(private val context: Context) : TrackersServ override fun stop(): Boolean { return when (state.value) { - TrackerServiceState.ON -> { - state.value = TrackerServiceState.STOPPING + FeatureServiceState.ON -> { + state.value = FeatureServiceState.STOPPING kotlin.runCatching { TrackersService.coroutineScope.cancel() } context.stopService(Intent(context, TrackersService::class.java)) true @@ -52,7 +52,7 @@ class TrackersServiceSupervisorImpl(private val context: Context) : TrackersServ } override fun isRunning(): Boolean { - return state.value != TrackerServiceState.OFF + return state.value != FeatureServiceState.OFF } } diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt index c1bb30e6..699e4b8e 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt @@ -95,7 +95,7 @@ class TunLooper( if (isPacketDNS(ipPacket)) handleDnsPacket(ipPacket) } } catch (e: Exception) { - Timber.w("Can't parse packet, ignore it.", e) + Timber.w(e, "Can't parse packet, ignore it.") } } @@ -153,7 +153,7 @@ class TunLooper( try { dataOutputStream?.write(it.rawData) } catch (e: IOException) { - Timber.e("error writing to VPN fd", e) + Timber.e(e, "error writing to VPN fd") } } } -- GitLab From 37f1bf570c192dbdf4060d9fb3eec4607e36459d Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Thu, 5 Oct 2023 09:09:47 +0200 Subject: [PATCH 5/5] Review fixes 3 --- .idea/.gitignore | 3 - .idea/.name | 1 - .idea/codeStyles/Project.xml | 167 ------------------ .idea/codeStyles/codeStyleConfig.xml | 5 - .idea/copyright/MURENA.xml | 6 - .idea/copyright/profiles_settings.xml | 3 - .idea/encodings.xml | 6 - .idea/inspectionProfiles/ktlint.xml | 7 - .../inspectionProfiles/profiles_settings.xml | 6 - .idea/runConfigurations/Build_system_app.xml | 13 -- .../e/advancedprivacy/Notifications.kt | 10 -- .../e/advancedprivacy/common/BuildFlavor.kt | 21 ++- .../usecases/IpScramblingStateUseCase.kt | 2 +- .../core/utils/NotificationsHelper.kt | 16 ++ .../domain/entities/NotificationChannels.kt | 16 ++ .../domain/entities/NotificationContent.kt | 16 ++ .../trackers/service/TrackersService.kt | 4 +- .../trackers/service/TunLooper.kt | 7 +- 18 files changed, 76 insertions(+), 233 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/.name delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/copyright/MURENA.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/inspectionProfiles/ktlint.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/runConfigurations/Build_system_app.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d33521..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 5f549977..00000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -AdvancedPrivacy diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 97c10636..00000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,167 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 0f7bc519..00000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/.idea/copyright/MURENA.xml b/.idea/copyright/MURENA.xml deleted file mode 100644 index 0c0ee957..00000000 --- a/.idea/copyright/MURENA.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e9f8efd4..00000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba4..00000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/ktlint.xml b/.idea/inspectionProfiles/ktlint.xml deleted file mode 100644 index 7d04a74b..00000000 --- a/.idea/inspectionProfiles/ktlint.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 64580d14..00000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/.idea/runConfigurations/Build_system_app.xml b/.idea/runConfigurations/Build_system_app.xml deleted file mode 100644 index 755d57a7..00000000 --- a/.idea/runConfigurations/Build_system_app.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt index 10bcd49a..455b1a78 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt @@ -45,16 +45,6 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach object Notifications { - // const val CHANNEL_FIRST_BOOT = "first_boot_notification" - // const val CHANNEL_FAKE_LOCATION_FLAG = "fake_location_flag" - // const val CHANNEL_IPSCRAMBLING_FLAG = "ipscrambling_flag" - // const val CHANNEL_TRACKER_FLAG = "tracker_flag" - // - // const val NOTIFICATION_FIRST_BOOT = 1000 - // const val NOTIFICATION_FAKE_LOCATION_FLAG = NOTIFICATION_FIRST_BOOT + 1 - // const val NOTIFICATION_IPSCRAMBLING_FLAG = NOTIFICATION_FAKE_LOCATION_FLAG + 1 - // const val NOTIFICATION_TRACKER_FLAG = NOTIFICATION_IPSCRAMBLING_FLAG + 1 - fun showFirstBootNotification(context: Context) { createNotificationFirstBootChannel(context) val notificationBuilder: NotificationCompat.Builder = notificationBuilder( diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt b/app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt index 0afa381f..ecb24ced 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/common/BuildFlavor.kt @@ -1,5 +1,22 @@ -package foundation.e.advancedprivacy.common.extensions +/* + * 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.common import foundation.e.advancedprivacy.BuildConfig -val isStandaloneBuild: Boolean = BuildConfig.FLAVOR == "standalone" +const val isStandaloneBuild: Boolean = BuildConfig.FLAVOR == "standalone" diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt index ec61b408..9c893290 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt @@ -19,7 +19,7 @@ package foundation.e.advancedprivacy.domain.usecases import android.content.Intent -import foundation.e.advancedprivacy.common.extensions.isStandaloneBuild +import foundation.e.advancedprivacy.common.isStandaloneBuild import foundation.e.advancedprivacy.data.repositories.AppListsRepository import foundation.e.advancedprivacy.data.repositories.LocalStateRepository import foundation.e.advancedprivacy.domain.entities.ApplicationDescription diff --git a/core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt b/core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt index 3e388570..29721b0b 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/core/utils/NotificationsHelper.kt @@ -1,3 +1,19 @@ +/* + * 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.core.utils import android.content.Context diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt index 7b01ac0f..4458e1df 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationChannels.kt @@ -1,3 +1,19 @@ +/* + * 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.domain.entities const val CHANNEL_FIRST_BOOT = "first_boot_notification" diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt index 04055ee8..44b508d0 100644 --- a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt +++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/NotificationContent.kt @@ -1,3 +1,19 @@ +/* + * 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.domain.entities import android.app.PendingIntent diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt index 28889a39..918977f6 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt @@ -85,7 +85,9 @@ class TrackersService : VpnService() { get(TunLooper::class.java).apply { listenJob(vpnInterface, coroutineScope) } - } else Timber.e("Cannot get VPN interface") + } else { + Timber.e("Cannot get VPN interface") + } } private fun initVPN(): ParcelFileDescriptor? { diff --git a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt index 699e4b8e..7813c674 100644 --- a/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt +++ b/trackersservicestandalone/src/main/java/foundation/e/advancedprivacy/trackers/service/TunLooper.kt @@ -92,7 +92,9 @@ class TunLooper( val packet = IpSelector.newPacket(pdata, 0, pdata.size) if (packet is IpPacket) { val ipPacket = packet - if (isPacketDNS(ipPacket)) handleDnsPacket(ipPacket) + if (isPacketDNS(ipPacket)) { + handleDnsPacket(ipPacket) + } } } catch (e: Exception) { Timber.w(e, "Can't parse packet, ignore it.") @@ -124,6 +126,7 @@ class TunLooper( .correctChecksumAtBuild(true) .correctLengthAtBuild(true) .payloadBuilder(dnsBuilder) + val respPacket: IpPacket? = if (ipPacket is IpV4Packet) { val ipV4Packet = ipPacket val ipv4Builder = IpV4Packet.Builder() @@ -158,7 +161,7 @@ class TunLooper( } } } catch (ioe: java.lang.Exception) { - Timber.e("could not parse DNS packet: $ioe") + Timber.e(ioe, "could not parse DNS packet") } } } -- GitLab