From 9d55978063947d5865bb3fa4e0c2ebef78f78812 Mon Sep 17 00:00:00 2001
From: Guillaume Jacquart <guillaume.jacquart@hoodbrains.com>
Date: Mon, 6 Nov 2023 08:14:27 +0000
Subject: epic18: Manage VPN services for Tor or Tracker control

---
 .../advancedprivacy/AdvancedPrivacyApplication.kt  |  5 +-
 .../foundation/e/advancedprivacy/KoinModule.kt     | 13 ++-
 .../foundation/e/advancedprivacy/Notifications.kt  | 28 +++----
 .../common/BootCompletedReceiver.kt                |  8 +-
 .../e/advancedprivacy/common/WarningDialog.kt      | 43 +++++-----
 .../data/repositories/LocalStateRepository.kt      | 54 ++++++------
 .../domain/entities/LocationMode.kt                | 22 -----
 .../domain/entities/MainFeatures.kt                | 22 -----
 .../domain/entities/ShowFeaturesWarning.kt         | 31 -------
 .../domain/usecases/FakeLocationStateUseCase.kt    |  9 +-
 .../domain/usecases/GetQuickPrivacyStateUseCase.kt | 13 +--
 .../domain/usecases/IpScramblingStateUseCase.kt    | 95 +++-------------------
 .../domain/usecases/ShowFeaturesWarningUseCase.kt  | 25 +++---
 .../domain/usecases/TrackersStateUseCase.kt        |  9 +-
 .../features/dashboard/DashboardFragment.kt        | 10 +--
 .../features/dashboard/DashboardState.kt           |  4 +-
 .../internetprivacy/InternetPrivacyFragment.kt     |  8 +-
 .../internetprivacy/InternetPrivacyState.kt        |  4 +-
 .../internetprivacy/InternetPrivacyViewModel.kt    |  4 +-
 .../e/advancedprivacy/widget/WidgetUI.kt           |  6 +-
 20 files changed, 138 insertions(+), 275 deletions(-)
 delete mode 100644 app/src/main/java/foundation/e/advancedprivacy/domain/entities/LocationMode.kt
 delete mode 100644 app/src/main/java/foundation/e/advancedprivacy/domain/entities/MainFeatures.kt
 delete mode 100644 app/src/main/java/foundation/e/advancedprivacy/domain/entities/ShowFeaturesWarning.kt

(limited to 'app/src/main/java/foundation')

diff --git a/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt b/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt
index 71fef00..0fc1d67 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2021 E FOUNDATION, 2022 - 2023 MURENA SAS
+ * Copyright (C) 2022 - 2023 MURENA SAS
+ * Copyright (C) 2021 E FOUNDATION
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,6 +26,7 @@ import foundation.e.advancedprivacy.domain.usecases.IpScramblingStateUseCase
 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.domain.usecases.VpnSupervisorUseCase
 import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule
 import foundation.e.advancedprivacy.trackers.services.UpdateTrackersWorker
 import foundation.e.lib.telemetry.Telemetry
@@ -70,5 +72,6 @@ class AdvancedPrivacyApplication : Application() {
         get<IpScramblingStateUseCase>(IpScramblingStateUseCase::class.java)
         get<TrackersStateUseCase>(TrackersStateUseCase::class.java)
         get<FakeLocationStateUseCase>(FakeLocationStateUseCase::class.java)
+        get<VpnSupervisorUseCase>(VpnSupervisorUseCase::class.java).listenSettings()
     }
 }
diff --git a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt
index fbf1252..efcd096 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt
@@ -20,11 +20,12 @@ package foundation.e.advancedprivacy
 import android.content.res.Resources
 import android.os.Process
 import foundation.e.advancedprivacy.core.coreModule
-import foundation.e.advancedprivacy.data.repositories.LocalStateRepository
+import foundation.e.advancedprivacy.data.repositories.LocalStateRepositoryImpl
 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.repositories.LocalStateRepository
 import foundation.e.advancedprivacy.domain.usecases.AppListUseCase
 import foundation.e.advancedprivacy.domain.usecases.FakeLocationStateUseCase
 import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase
@@ -55,8 +56,8 @@ val appModule = module {
     includes(coreModule, trackersModule, fakelocationModule, ipScramblerModule, trackerServiceModule)
 
     factory<Resources> { androidContext().resources }
-    single {
-        LocalStateRepository(context = androidContext())
+    single<LocalStateRepository> {
+        LocalStateRepositoryImpl(context = androidContext())
     }
 
     single<ApplicationDescription>(named("AdvancedPrivacy")) {
@@ -120,15 +121,13 @@ val appModule = module {
     singleOf(::GetQuickPrivacyStateUseCase)
     single {
         IpScramblingStateUseCase(
-            orbotServiceSupervisor = get(),
-            permissionsPrivacyModule = get(),
-            appDesc = get(named("AdvancedPrivacy")),
+            orbotSupervisor = get(),
             localStateRepository = get(),
             appListsRepository = get(),
-            trackersServiceSupervisor = get(),
             coroutineScope = get()
         )
     }
+
     singleOf(::ShowFeaturesWarningUseCase)
     singleOf(::TrackersStateUseCase)
     singleOf(::TrackersStatisticsUseCase)
diff --git a/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt
index 639ede4..430e9d5 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt
@@ -29,8 +29,7 @@ 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.FeatureServiceState
-import foundation.e.advancedprivacy.domain.entities.MainFeatures
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 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
@@ -98,19 +97,19 @@ object Notifications {
 
         getQuickPrivacyStateUseCase.isLocationHidden.onEach {
             if (it) {
-                showFlagNotification(appContext, MainFeatures.FAKE_LOCATION)
+                showFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG)
             } else {
-                hideFlagNotification(appContext, MainFeatures.FAKE_LOCATION)
+                hideFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG)
             }
         }.launchIn(appScope)
 
         getQuickPrivacyStateUseCase.ipScramblingMode.map {
-            it != FeatureServiceState.OFF
+            it != FeatureState.OFF
         }.distinctUntilChanged().onEach {
             if (it) {
-                showFlagNotification(appContext, MainFeatures.IP_SCRAMBLING)
+                showFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG)
             } else {
-                hideFlagNotification(appContext, MainFeatures.IP_SCRAMBLING)
+                hideFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG)
             }
         }.launchIn(appScope)
     }
@@ -139,9 +138,9 @@ object Notifications {
         NotificationManagerCompat.from(context).createNotificationChannel(channel)
     }
 
-    private fun showFlagNotification(context: Context, feature: MainFeatures) {
-        when (feature) {
-            MainFeatures.FAKE_LOCATION -> showFlagNotification(
+    private fun showFlagNotification(context: Context, id: Int) {
+        when (id) {
+            NOTIFICATION_FAKE_LOCATION_FLAG -> showFlagNotification(
                 context = context,
                 id = NOTIFICATION_FAKE_LOCATION_FLAG,
                 content = NotificationContent(
@@ -154,7 +153,7 @@ object Notifications {
                         .createPendingIntent()
                 )
             )
-            MainFeatures.IP_SCRAMBLING -> showFlagNotification(
+            NOTIFICATION_IPSCRAMBLING_FLAG -> showFlagNotification(
                 context = context,
                 id = NOTIFICATION_IPSCRAMBLING_FLAG,
                 content = NotificationContent(
@@ -183,12 +182,7 @@ object Notifications {
         NotificationManagerCompat.from(context).notify(id, builder.build())
     }
 
-    private fun hideFlagNotification(context: Context, feature: MainFeatures) {
-        val id = when (feature) {
-            MainFeatures.FAKE_LOCATION -> NOTIFICATION_FAKE_LOCATION_FLAG
-            MainFeatures.IP_SCRAMBLING -> NOTIFICATION_IPSCRAMBLING_FLAG
-            else -> return
-        }
+    private fun hideFlagNotification(context: Context, id: Int) {
         NotificationManagerCompat.from(context).cancel(id)
     }
 }
diff --git a/app/src/main/java/foundation/e/advancedprivacy/common/BootCompletedReceiver.kt b/app/src/main/java/foundation/e/advancedprivacy/common/BootCompletedReceiver.kt
index d73f770..562144d 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/common/BootCompletedReceiver.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/common/BootCompletedReceiver.kt
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2023 MURENA SAS
  * Copyright (C) 2022 E FOUNDATION
  *
  * This program is free software: you can redistribute it and/or modify
@@ -21,12 +22,15 @@ import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
 import foundation.e.advancedprivacy.Notifications
-import foundation.e.advancedprivacy.data.repositories.LocalStateRepository
+import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
+import org.koin.java.KoinJavaComponent.inject
 
 class BootCompletedReceiver : BroadcastReceiver() {
+
+    private val localStateRepository by inject<LocalStateRepository>(LocalStateRepository::class.java)
+
     override fun onReceive(context: Context, intent: Intent?) {
         if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
-            val localStateRepository = LocalStateRepository(context)
             if (localStateRepository.firstBoot) {
                 Notifications.showFirstBootNotification(context)
                 localStateRepository.firstBoot = false
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 589aa74..9dbfea9 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/common/WarningDialog.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/common/WarningDialog.kt
@@ -29,9 +29,12 @@ import androidx.activity.result.contract.ActivityResultContracts
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.app.AppCompatActivity
 import foundation.e.advancedprivacy.R
-import foundation.e.advancedprivacy.domain.entities.ShowFeaturesWarning
-import foundation.e.advancedprivacy.domain.usecases.IpScramblingStateUseCase
+import foundation.e.advancedprivacy.domain.entities.MainFeatures
+import foundation.e.advancedprivacy.domain.entities.MainFeatures.FakeLocation
+import foundation.e.advancedprivacy.domain.entities.MainFeatures.IpScrambling
+import foundation.e.advancedprivacy.domain.entities.MainFeatures.TrackersControl
 import foundation.e.advancedprivacy.domain.usecases.ShowFeaturesWarningUseCase
+import foundation.e.advancedprivacy.domain.usecases.VpnSupervisorUseCase
 import foundation.e.advancedprivacy.main.MainActivity
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.launchIn
@@ -57,7 +60,7 @@ class WarningDialog : AppCompatActivity() {
 
         private fun createIntent(
             context: Context,
-            feature: ShowFeaturesWarning,
+            feature: MainFeatures,
         ): Intent {
             val intent = Intent(context, WarningDialog::class.java)
             intent.putExtra(PARAM_FEATURE, feature)
@@ -67,13 +70,14 @@ class WarningDialog : AppCompatActivity() {
     }
 
     private var isWaitingForResult = false
+    private lateinit var feature: MainFeatures
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         window.setBackgroundDrawable(ColorDrawable(0))
 
-        val feature = try {
-            intent.getParcelableExtra<ShowFeaturesWarning>(PARAM_FEATURE)!!
+        feature = try {
+            intent.getParcelableExtra<MainFeatures>(PARAM_FEATURE)!!
         } catch (e: Exception) {
             Timber.e(e, "Missing mandatory activity parameter")
             finish()
@@ -82,7 +86,7 @@ class WarningDialog : AppCompatActivity() {
         showWarningDialog(feature)
     }
 
-    private fun showWarningDialog(feature: ShowFeaturesWarning) {
+    private fun showWarningDialog(feature: MainFeatures) {
         val builder = AlertDialog.Builder(this)
         builder.setOnDismissListener { if (!isWaitingForResult) finish() }
 
@@ -92,23 +96,23 @@ class WarningDialog : AppCompatActivity() {
 
         builder.setMessage(
             when (feature) {
-                ShowFeaturesWarning.TrackersControl -> R.string.warningdialog_trackers_message
-                ShowFeaturesWarning.FakeLocation -> R.string.warningdialog_location_message
-                is ShowFeaturesWarning.IpScrambling -> R.string.warningdialog_ipscrambling_message
+                is TrackersControl -> R.string.warningdialog_trackers_message
+                is FakeLocation -> R.string.warningdialog_location_message
+                is IpScrambling -> R.string.warningdialog_ipscrambling_message
             }
         )
 
         builder.setTitle(
             when (feature) {
-                ShowFeaturesWarning.TrackersControl -> R.string.warningdialog_trackers_title
-                ShowFeaturesWarning.FakeLocation -> R.string.warningdialog_location_title
-                is ShowFeaturesWarning.IpScrambling -> R.string.warningdialog_ipscrambling_title
+                is TrackersControl -> R.string.warningdialog_trackers_title
+                is FakeLocation -> R.string.warningdialog_location_title
+                is IpScrambling -> R.string.warningdialog_ipscrambling_title
             }
         )
 
         builder.setPositiveButton(
             when (feature) {
-                is ShowFeaturesWarning.IpScrambling -> R.string.warningdialog_ipscrambling_cta
+                is IpScrambling -> R.string.warningdialog_ipscrambling_cta
                 else -> R.string.ok
             }
         ) { _, _ ->
@@ -117,7 +121,7 @@ class WarningDialog : AppCompatActivity() {
                     .doNotShowAgain(feature)
             }
 
-            val vpnDisclaimerIntent = (feature as? ShowFeaturesWarning.IpScrambling)
+            val vpnDisclaimerIntent = (feature as? MainFeatures.IpScrambling)
                 ?.startVpnDisclaimer
 
             if (vpnDisclaimerIntent != null) {
@@ -126,7 +130,7 @@ class WarningDialog : AppCompatActivity() {
             } else finish()
         }
 
-        if (feature == ShowFeaturesWarning.TrackersControl) {
+        if (feature is MainFeatures.TrackersControl) {
             builder.setNeutralButton(R.string.warningdialog_trackers_secondary_cta) { _, _ ->
                 MainActivity.deepLinkBuilder(this)
                     .setDestination(R.id.trackersFragment)
@@ -135,16 +139,17 @@ class WarningDialog : AppCompatActivity() {
                 finish()
             }
         }
-
         builder.show()
     }
 
     private val launchAndroidVpnDisclaimer = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
-        val ipScramblingStateUseCase = get<IpScramblingStateUseCase>(IpScramblingStateUseCase::class.java)
+        val vpnSupervisorUseCase = get<VpnSupervisorUseCase>(
+            VpnSupervisorUseCase::class.java
+        )
         if (result.resultCode == Activity.RESULT_OK) {
-            ipScramblingStateUseCase.startIpScrambling()
+            vpnSupervisorUseCase.startVpnService(feature)
         } else {
-            ipScramblingStateUseCase.toggle(false)
+            vpnSupervisorUseCase.cancelStartVpnService(feature)
         }
         finish()
     }
diff --git a/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt b/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt
index c7d4a27..2afd6ee 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/data/repositories/LocalStateRepository.kt
@@ -19,18 +19,18 @@
 package foundation.e.advancedprivacy.data.repositories
 
 import android.content.Context
-import android.content.Intent
 import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 import foundation.e.advancedprivacy.domain.entities.LocationMode
-import foundation.e.advancedprivacy.domain.entities.ShowFeaturesWarning
+import foundation.e.advancedprivacy.domain.entities.MainFeatures
+import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.update
 
-class LocalStateRepository(context: Context) {
+class LocalStateRepositoryImpl(context: Context) : LocalStateRepository {
     companion object {
         private const val SHARED_PREFS_FILE = "localState"
         private const val KEY_BLOCK_TRACKERS = "blockTrackers"
@@ -47,25 +47,26 @@ class LocalStateRepository(context: Context) {
     private val sharedPref = context.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE)
 
     private val _blockTrackers = MutableStateFlow(sharedPref.getBoolean(KEY_BLOCK_TRACKERS, true))
-    val blockTrackers = _blockTrackers.asStateFlow()
 
-    fun setBlockTrackers(enabled: Boolean) {
+    override val blockTrackers = _blockTrackers.asStateFlow()
+
+    override fun setBlockTrackers(enabled: Boolean) {
         set(KEY_BLOCK_TRACKERS, enabled)
         _blockTrackers.update { enabled }
     }
 
-    val areAllTrackersBlocked: MutableStateFlow<Boolean> = MutableStateFlow(false)
+    override val areAllTrackersBlocked: MutableStateFlow<Boolean> = MutableStateFlow(false)
 
     private val _fakeLocationEnabled = MutableStateFlow(sharedPref.getBoolean(KEY_FAKE_LOCATION, false))
 
-    val fakeLocationEnabled = _fakeLocationEnabled.asStateFlow()
+    override val fakeLocationEnabled = _fakeLocationEnabled.asStateFlow()
 
-    fun setFakeLocationEnabled(enabled: Boolean) {
+    override fun setFakeLocationEnabled(enabled: Boolean) {
         set(KEY_FAKE_LOCATION, enabled)
         _fakeLocationEnabled.update { enabled }
     }
 
-    var fakeLocation: Pair<Float, Float>
+    override var fakeLocation: Pair<Float, Float>
         get() = Pair(
             // Initial default value is Quezon City
             sharedPref.getFloat(KEY_FAKE_LATITUDE, 14.6760f),
@@ -79,43 +80,48 @@ class LocalStateRepository(context: Context) {
                 .apply()
         }
 
-    val locationMode: MutableStateFlow<LocationMode> = MutableStateFlow(LocationMode.REAL_LOCATION)
+    override val locationMode: MutableStateFlow<LocationMode> = MutableStateFlow(LocationMode.REAL_LOCATION)
 
     private val _ipScramblingSetting = MutableStateFlow(sharedPref.getBoolean(KEY_IP_SCRAMBLING, false))
-    val ipScramblingSetting = _ipScramblingSetting.asStateFlow()
 
-    fun setIpScramblingSetting(enabled: Boolean) {
+    override val ipScramblingSetting = _ipScramblingSetting.asStateFlow()
+
+    override fun setIpScramblingSetting(enabled: Boolean) {
         set(KEY_IP_SCRAMBLING, enabled)
         _ipScramblingSetting.update { enabled }
     }
 
-    val internetPrivacyMode: MutableStateFlow<FeatureServiceState> = MutableStateFlow(FeatureServiceState.OFF)
+    override val internetPrivacyMode: MutableStateFlow<FeatureState> = MutableStateFlow(FeatureState.OFF)
+
+    private val _startVpnDisclaimer = MutableSharedFlow<MainFeatures>()
 
-    private val _startVpnDisclaimer = MutableSharedFlow<ShowFeaturesWarning.IpScrambling>()
-    suspend fun emitStartVpnDisclaimer(intent: Intent?) {
-        _startVpnDisclaimer.emit(ShowFeaturesWarning.IpScrambling(startVpnDisclaimer = intent))
+    override suspend fun emitStartVpnDisclaimer(feature: MainFeatures) {
+        _startVpnDisclaimer.emit(feature)
     }
-    val startVpnDisclaimer: SharedFlow<ShowFeaturesWarning.IpScrambling> = _startVpnDisclaimer
+
+    override val startVpnDisclaimer: SharedFlow<MainFeatures> = _startVpnDisclaimer
 
     private val _otherVpnRunning = MutableSharedFlow<ApplicationDescription>()
-    suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) {
+
+    override suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) {
         _otherVpnRunning.emit(appDesc)
     }
-    val otherVpnRunning: SharedFlow<ApplicationDescription> = _otherVpnRunning
 
-    var firstBoot: Boolean
+    override val otherVpnRunning: SharedFlow<ApplicationDescription> = _otherVpnRunning
+
+    override var firstBoot: Boolean
         get() = sharedPref.getBoolean(KEY_FIRST_BOOT, true)
         set(value) = set(KEY_FIRST_BOOT, value)
 
-    var hideWarningTrackers: Boolean
+    override var hideWarningTrackers: Boolean
         get() = sharedPref.getBoolean(KEY_HIDE_WARNING_TRACKERS, false)
         set(value) = set(KEY_HIDE_WARNING_TRACKERS, value)
 
-    var hideWarningLocation: Boolean
+    override var hideWarningLocation: Boolean
         get() = sharedPref.getBoolean(KEY_HIDE_WARNING_LOCATION, false)
         set(value) = set(KEY_HIDE_WARNING_LOCATION, value)
 
-    var hideWarningIpScrambling: Boolean
+    override var hideWarningIpScrambling: Boolean
         get() = sharedPref.getBoolean(KEY_HIDE_WARNING_IPSCRAMBLING, false)
         set(value) = set(KEY_HIDE_WARNING_IPSCRAMBLING, value)
 
diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/LocationMode.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/entities/LocationMode.kt
deleted file mode 100644
index 62581eb..0000000
--- a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/LocationMode.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2021 E FOUNDATION
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.advancedprivacy.domain.entities
-
-enum class LocationMode {
-    REAL_LOCATION, RANDOM_LOCATION, SPECIFIC_LOCATION
-}
diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/MainFeatures.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/entities/MainFeatures.kt
deleted file mode 100644
index c63d3ab..0000000
--- a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/MainFeatures.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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 <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.advancedprivacy.domain.entities
-
-enum class MainFeatures {
-    TRACKERS_CONTROL, FAKE_LOCATION, IP_SCRAMBLING
-}
diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/ShowFeaturesWarning.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/entities/ShowFeaturesWarning.kt
deleted file mode 100644
index 0d8e0e8..0000000
--- a/app/src/main/java/foundation/e/advancedprivacy/domain/entities/ShowFeaturesWarning.kt
+++ /dev/null
@@ -1,31 +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 <https://www.gnu.org/licenses/>.
- */
-package foundation.e.advancedprivacy.domain.entities
-
-import android.content.Intent
-import android.os.Parcelable
-import kotlinx.parcelize.Parcelize
-
-sealed class ShowFeaturesWarning : Parcelable {
-    @Parcelize
-    object TrackersControl : ShowFeaturesWarning()
-    @Parcelize
-    object FakeLocation : ShowFeaturesWarning()
-    @Parcelize
-    data class IpScrambling(val startVpnDisclaimer: Intent? = null) : ShowFeaturesWarning()
-}
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 983ba71..282116e 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
@@ -25,10 +25,10 @@ import android.location.Location
 import android.location.LocationListener
 import android.location.LocationManager
 import android.os.Bundle
-import foundation.e.advancedprivacy.data.repositories.LocalStateRepository
 import foundation.e.advancedprivacy.domain.entities.AppOpModes
 import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
 import foundation.e.advancedprivacy.domain.entities.LocationMode
+import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
 import foundation.e.advancedprivacy.dummy.CityDataSource
 import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule
 import foundation.e.advancedprivacy.fakelocation.domain.usecases.FakeLocationModule
@@ -49,11 +49,10 @@ class FakeLocationStateUseCase(
     private val appContext: Context,
     coroutineScope: CoroutineScope
 ) {
-    companion object {
-        private const val TAG = "FakeLocationStateUseCase"
-    }
+    private val _configuredLocationMode = MutableStateFlow<Triple<LocationMode, Float?, Float?>>(
+        Triple(LocationMode.REAL_LOCATION, null, null)
+    )
 
-    private val _configuredLocationMode = MutableStateFlow<Triple<LocationMode, Float?, Float?>>(Triple(LocationMode.REAL_LOCATION, null, null))
     val configuredLocationMode: StateFlow<Triple<LocationMode, Float?, Float?>> = _configuredLocationMode
 
     init {
diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/GetQuickPrivacyStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/GetQuickPrivacyStateUseCase.kt
index 1b8f62c..480d3b3 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/GetQuickPrivacyStateUseCase.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/GetQuickPrivacyStateUseCase.kt
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2023 MURENA SAS
  * Copyright (C) 2021 E FOUNDATION
  *
  * This program is free software: you can redistribute it and/or modify
@@ -17,12 +18,12 @@
 
 package foundation.e.advancedprivacy.domain.usecases
 
-import foundation.e.advancedprivacy.data.repositories.LocalStateRepository
 import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 import foundation.e.advancedprivacy.domain.entities.LocationMode
 import foundation.e.advancedprivacy.domain.entities.QuickPrivacyState
 import foundation.e.advancedprivacy.domain.entities.TrackerMode
+import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -41,13 +42,13 @@ class GetQuickPrivacyStateUseCase(
         when {
             !isBlockTrackers &&
                 locationMode == LocationMode.REAL_LOCATION &&
-                internetPrivacyMode == FeatureServiceState.OFF -> QuickPrivacyState.DISABLED
+                internetPrivacyMode == FeatureState.OFF -> QuickPrivacyState.DISABLED
 
             isAllTrackersBlocked &&
                 locationMode != LocationMode.REAL_LOCATION &&
                 internetPrivacyMode in listOf(
-                FeatureServiceState.ON,
-                FeatureServiceState.STARTING
+                FeatureState.ON,
+                FeatureState.STARTING
             ) -> QuickPrivacyState.FULL_ENABLED
 
             else -> QuickPrivacyState.ENABLED
@@ -71,7 +72,7 @@ class GetQuickPrivacyStateUseCase(
 
     val locationMode: StateFlow<LocationMode> = localStateRepository.locationMode
 
-    val ipScramblingMode: Flow<FeatureServiceState> =
+    val ipScramblingMode: Flow<FeatureState> =
         localStateRepository.internetPrivacyMode
 
     fun toggleTrackers(enabled: Boolean?) {
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 79c79f7..00613dd 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
@@ -18,43 +18,27 @@
 
 package foundation.e.advancedprivacy.domain.usecases
 
-import android.content.Intent
-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
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
-import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule
-import foundation.e.advancedprivacy.ipscrambler.OrbotServiceSupervisor
-import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor
+import foundation.e.advancedprivacy.domain.entities.FeatureState
+import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
+import foundation.e.advancedprivacy.ipscrambler.OrbotSupervisor
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.launch
 
 class IpScramblingStateUseCase(
-    private val orbotServiceSupervisor: OrbotServiceSupervisor,
-    private val permissionsPrivacyModule: IPermissionsPrivacyModule,
-    private val appDesc: ApplicationDescription,
+    private val orbotSupervisor: OrbotSupervisor,
     private val localStateRepository: LocalStateRepository,
     private val appListsRepository: AppListsRepository,
-    private val trackersServiceSupervisor: TrackersServiceSupervisor,
     private val coroutineScope: CoroutineScope
 ) {
-    val internetPrivacyMode: StateFlow<FeatureServiceState> = orbotServiceSupervisor.state
+    val internetPrivacyMode: StateFlow<FeatureState> = orbotSupervisor.state
 
     init {
-        orbotServiceSupervisor.requestStatus()
+        orbotSupervisor.requestStatus()
 
-        coroutineScope.launch(Dispatchers.Default) {
-            localStateRepository.ipScramblingSetting.collect {
-                applySettings(it)
-            }
-        }
-
-        orbotServiceSupervisor.state.map {
+        orbotSupervisor.state.map {
             localStateRepository.internetPrivacyMode.value = it
         }.launchIn(coroutineScope)
     }
@@ -68,7 +52,7 @@ class IpScramblingStateUseCase(
     }
 
     val bypassTorApps: Set<String> get() {
-        var whitelist = orbotServiceSupervisor.appList
+        var whitelist = orbotSupervisor.appList
         if (getHiddenPackageNames().any { it in whitelist }) {
             val mutable = whitelist.toMutableSet()
             mutable.removeAll(getHiddenPackageNames())
@@ -86,7 +70,7 @@ class IpScramblingStateUseCase(
 
     fun toggleBypassTor(packageName: String) {
         val visibleList = bypassTorApps.toMutableSet()
-        val rawList = orbotServiceSupervisor.appList.toMutableSet()
+        val rawList = orbotSupervisor.appList.toMutableSet()
 
         if (visibleList.contains(packageName)) {
             if (packageName == appListsRepository.dummySystemApp.packageName) {
@@ -105,69 +89,16 @@ class IpScramblingStateUseCase(
                 rawList.add(packageName)
             }
         }
-        orbotServiceSupervisor.appList = rawList
+        orbotSupervisor.appList = rawList
     }
 
-    val availablesLocations: List<String> = orbotServiceSupervisor.getAvailablesLocations().sorted()
+    val availablesLocations: List<String> = orbotSupervisor.getAvailablesLocations().sorted()
 
-    val exitCountry: String get() = orbotServiceSupervisor.getExitCountryCode()
+    val exitCountry: String get() = orbotSupervisor.getExitCountryCode()
 
     suspend fun setExitCountry(locationId: String) {
         if (locationId != exitCountry) {
-            orbotServiceSupervisor.setExitCountryCode(locationId)
+            orbotSupervisor.setExitCountryCode(locationId)
         }
     }
-
-    private suspend fun applySettings(isIpScramblingEnabled: Boolean) {
-        val currentMode = localStateRepository.internetPrivacyMode.value
-        when {
-            isIpScramblingEnabled && currentMode in setOf(FeatureServiceState.OFF, FeatureServiceState.STOPPING) ->
-                applyStartIpScrambling()
-
-            !isIpScramblingEnabled && currentMode in setOf(FeatureServiceState.ON, FeatureServiceState.STARTING) ->
-                orbotServiceSupervisor.stop()
-
-            else -> {}
-        }
-    }
-
-    private suspend fun applyStartIpScrambling() {
-        val authorizeVpnIntent = orbotServiceSupervisor.prepareAndroidVpn()
-        if (authorizeVpnIntent == null) {
-            localStateRepository.emitStartVpnDisclaimer(null)
-
-            startIpScrambling()
-            return
-        }
-
-        acquireVpnAuthorization(authorizeVpnIntent)
-    }
-
-    private suspend fun acquireVpnAuthorization(authorizeVpnIntent: Intent) {
-        val authorized = permissionsPrivacyModule.setVpnPackageAuthorization(appDesc.packageName)
-        val alwaysOnVpnPackage = permissionsPrivacyModule.getAlwaysOnVpnPackage()
-
-        when {
-            authorized && alwaysOnVpnPackage == null -> {
-                localStateRepository.emitStartVpnDisclaimer(null)
-                startIpScrambling()
-            }
-            authorized && alwaysOnVpnPackage != null -> {
-                localStateRepository.emitOtherVpnRunning(
-                    permissionsPrivacyModule.getApplicationDescription(
-                        packageName = alwaysOnVpnPackage,
-                        withIcon = false
-                    )
-                )
-                localStateRepository.setIpScramblingSetting(enabled = false)
-            }
-            else -> localStateRepository.emitStartVpnDisclaimer(authorizeVpnIntent)
-        }
-    }
-
-    fun startIpScrambling() {
-        localStateRepository.internetPrivacyMode.value = FeatureServiceState.STARTING
-        orbotServiceSupervisor.setDNSFilter((trackersServiceSupervisor.dnsFilterForIpScrambling))
-        orbotServiceSupervisor.start(enableNotification = isStandaloneBuild)
-    }
 }
diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/ShowFeaturesWarningUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/ShowFeaturesWarningUseCase.kt
index c99d5f1..f8a0986 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/ShowFeaturesWarningUseCase.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/ShowFeaturesWarningUseCase.kt
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2023 MURENA SAS
  * Copyright (C) 2022 E FOUNDATION
  *
  * This program is free software: you can redistribute it and/or modify
@@ -17,11 +18,11 @@
 
 package foundation.e.advancedprivacy.domain.usecases
 
-import foundation.e.advancedprivacy.data.repositories.LocalStateRepository
-import foundation.e.advancedprivacy.domain.entities.ShowFeaturesWarning
-import foundation.e.advancedprivacy.domain.entities.ShowFeaturesWarning.FakeLocation
-import foundation.e.advancedprivacy.domain.entities.ShowFeaturesWarning.IpScrambling
-import foundation.e.advancedprivacy.domain.entities.ShowFeaturesWarning.TrackersControl
+import foundation.e.advancedprivacy.domain.entities.MainFeatures
+import foundation.e.advancedprivacy.domain.entities.MainFeatures.FakeLocation
+import foundation.e.advancedprivacy.domain.entities.MainFeatures.IpScrambling
+import foundation.e.advancedprivacy.domain.entities.MainFeatures.TrackersControl
+import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.drop
 import kotlinx.coroutines.flow.dropWhile
@@ -33,24 +34,22 @@ class ShowFeaturesWarningUseCase(
     private val localStateRepository: LocalStateRepository
 ) {
 
-    fun showWarning(): Flow<ShowFeaturesWarning> {
+    fun showWarning(): Flow<MainFeatures> {
         return merge(
-            localStateRepository.blockTrackers.drop(1).dropWhile { !it }
-                .filter { it && !localStateRepository.hideWarningTrackers }
-                .map { TrackersControl },
             localStateRepository.fakeLocationEnabled.drop(1).dropWhile { !it }
                 .filter { it && !localStateRepository.hideWarningLocation }
                 .map { FakeLocation },
             localStateRepository.startVpnDisclaimer.filter {
-                it.startVpnDisclaimer != null || !localStateRepository.hideWarningIpScrambling
+                (it is IpScrambling && !localStateRepository.hideWarningIpScrambling) ||
+                    (it is TrackersControl && !localStateRepository.hideWarningTrackers)
             }
         )
     }
 
-    fun doNotShowAgain(feature: ShowFeaturesWarning) {
+    fun doNotShowAgain(feature: MainFeatures) {
         when (feature) {
-            TrackersControl -> localStateRepository.hideWarningTrackers = true
-            FakeLocation -> localStateRepository.hideWarningLocation = true
+            is TrackersControl -> localStateRepository.hideWarningTrackers = true
+            is FakeLocation -> localStateRepository.hideWarningLocation = true
             is IpScrambling -> localStateRepository.hideWarningIpScrambling = true
         }
     }
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 9b79dcc..2c47d70 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
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2021 E FOUNDATION, 2022 - 2023 MURENA SAS
+ * Copyright (C) 2022 - 2023 MURENA SAS
+ * Copyright (C) 2021 E FOUNDATION
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,11 +19,10 @@
 package foundation.e.advancedprivacy.domain.usecases
 
 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.domain.repositories.LocalStateRepository
 import foundation.e.advancedprivacy.trackers.data.WhitelistRepository
 import foundation.e.advancedprivacy.trackers.domain.entities.Tracker
-import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersServiceSupervisor
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 
@@ -30,7 +30,6 @@ class TrackersStateUseCase(
     private val whitelistRepository: WhitelistRepository,
     private val localStateRepository: LocalStateRepository,
     private val appListsRepository: AppListsRepository,
-    private val trackersServiceSupervisor: TrackersServiceSupervisor,
     coroutineScope: CoroutineScope,
 ) {
     init {
@@ -40,8 +39,6 @@ class TrackersStateUseCase(
                 updateAllTrackersBlockedState()
             }
         }
-
-        trackersServiceSupervisor.start()
     }
 
     private fun updateAllTrackersBlockedState() {
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt
index 0a53c6c..56cf81f 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardFragment.kt
@@ -34,7 +34,7 @@ import foundation.e.advancedprivacy.R
 import foundation.e.advancedprivacy.common.GraphHolder
 import foundation.e.advancedprivacy.common.NavToolbarFragment
 import foundation.e.advancedprivacy.databinding.FragmentDashboardBinding
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 import foundation.e.advancedprivacy.domain.entities.LocationMode
 import foundation.e.advancedprivacy.domain.entities.QuickPrivacyState
 import foundation.e.advancedprivacy.domain.entities.TrackerMode
@@ -186,11 +186,11 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
         binding.toggleIpscrambling.isChecked = state.ipScramblingMode.isChecked
         val isLoading = state.ipScramblingMode.isLoading
         binding.toggleIpscrambling.isEnabled = (
-            state.ipScramblingMode != FeatureServiceState.STOPPING
+            state.ipScramblingMode != FeatureState.STOPPING
             )
 
         binding.stateIpAddress.text = getString(
-            if (state.ipScramblingMode == FeatureServiceState.ON) R.string.dashboard_state_ipaddress_on
+            if (state.ipScramblingMode == FeatureState.ON) R.string.dashboard_state_ipaddress_on
             else R.string.dashboard_state_ipaddress_off
         )
 
@@ -200,7 +200,7 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
         binding.stateIpAddress.setTextColor(
             getColor(
                 requireContext(),
-                if (state.ipScramblingMode == FeatureServiceState.ON) R.color.green_valid
+                if (state.ipScramblingMode == FeatureState.ON) R.color.green_valid
                 else R.color.red_off
             )
         )
@@ -250,7 +250,7 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
         )
 
         binding.internetActivityPrivacy.subTitle = getString(
-            if (state.ipScramblingMode == FeatureServiceState.ON) R.string.dashboard_internet_activity_privacy_subtitle_on
+            if (state.ipScramblingMode == FeatureState.ON) R.string.dashboard_internet_activity_privacy_subtitle_on
             else R.string.dashboard_internet_activity_privacy_subtitle_off
         )
 
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardState.kt b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardState.kt
index 069ff04..d26c53d 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardState.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/dashboard/DashboardState.kt
@@ -17,7 +17,7 @@
 
 package foundation.e.advancedprivacy.features.dashboard
 
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 import foundation.e.advancedprivacy.domain.entities.LocationMode
 import foundation.e.advancedprivacy.domain.entities.QuickPrivacyState
 import foundation.e.advancedprivacy.domain.entities.TrackerMode
@@ -26,7 +26,7 @@ data class DashboardState(
     val quickPrivacyState: QuickPrivacyState = QuickPrivacyState.DISABLED,
     val trackerMode: TrackerMode = TrackerMode.VULNERABLE,
     val isLocationHidden: Boolean = false,
-    val ipScramblingMode: FeatureServiceState = FeatureServiceState.STOPPING,
+    val ipScramblingMode: FeatureState = FeatureState.STOPPING,
     val locationMode: LocationMode = LocationMode.REAL_LOCATION,
     val leakedTrackersCount: Int? = null,
     val trackersCount: Int? = null,
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt
index b4fc8a1..482a773 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyFragment.kt
@@ -32,7 +32,7 @@ import foundation.e.advancedprivacy.common.NavToolbarFragment
 import foundation.e.advancedprivacy.common.ToggleAppsAdapter
 import foundation.e.advancedprivacy.common.setToolTipForAsterisk
 import foundation.e.advancedprivacy.databinding.FragmentInternetActivityPolicyBinding
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 import kotlinx.coroutines.launch
 import org.koin.androidx.viewmodel.ext.android.viewModel
 import java.util.Locale
@@ -137,11 +137,11 @@ class InternetPrivacyFragment : NavToolbarFragment(R.layout.fragment_internet_ac
     private fun render(state: InternetPrivacyState) {
         binding.radioUseHiddenIp.radiobutton.apply {
             isChecked = state.mode.isChecked
-            isEnabled = state.mode != FeatureServiceState.STARTING
+            isEnabled = state.mode != FeatureState.STARTING
         }
         binding.radioUseRealIp.radiobutton.apply {
             isChecked = !state.mode.isChecked
-            isEnabled = state.mode != FeatureServiceState.STOPPING
+            isEnabled = state.mode != FeatureState.STOPPING
         }
 
         binding.ipscramblingSelectLocation.setSelection(state.selectedLocationPosition)
@@ -150,7 +150,7 @@ class InternetPrivacyFragment : NavToolbarFragment(R.layout.fragment_internet_ac
         binding.apps.post {
             (binding.apps.adapter as ToggleAppsAdapter?)?.setData(
                 list = state.getApps(),
-                isEnabled = state.mode == FeatureServiceState.ON
+                isEnabled = state.mode == FeatureState.ON
             )
         }
 
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyState.kt b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyState.kt
index e607d6c..9ba716f 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyState.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyState.kt
@@ -18,10 +18,10 @@
 package foundation.e.advancedprivacy.features.internetprivacy
 
 import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 
 data class InternetPrivacyState(
-    val mode: FeatureServiceState = FeatureServiceState.OFF,
+    val mode: FeatureState = FeatureState.OFF,
     val availableApps: List<ApplicationDescription> = emptyList(),
     val bypassTorApps: Collection<String> = emptyList(),
     val selectedLocation: String = "",
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt
index 10530e1..b2f93c2 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt
@@ -22,7 +22,7 @@ import androidx.annotation.StringRes
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import foundation.e.advancedprivacy.R
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 import foundation.e.advancedprivacy.domain.usecases.AppListUseCase
 import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase
 import foundation.e.advancedprivacy.domain.usecases.IpScramblingStateUseCase
@@ -88,7 +88,7 @@ class InternetPrivacyViewModel(
 
         launch {
             ipScramblingStateUseCase.internetPrivacyMode
-                .map { it == FeatureServiceState.STARTING }
+                .map { it == FeatureState.STARTING }
                 .debounce(WARNING_LOADING_LONG_DELAY)
                 .collect {
                     if (it) _singleEvents.emit(
diff --git a/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt b/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt
index 1bd8693..e3454b9 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/widget/WidgetUI.kt
@@ -31,7 +31,7 @@ import foundation.e.advancedprivacy.R
 import foundation.e.advancedprivacy.Widget
 import foundation.e.advancedprivacy.Widget.Companion.isDarkText
 import foundation.e.advancedprivacy.common.extensions.dpToPxF
-import foundation.e.advancedprivacy.domain.entities.FeatureServiceState
+import foundation.e.advancedprivacy.domain.entities.FeatureState
 import foundation.e.advancedprivacy.domain.entities.QuickPrivacyState
 import foundation.e.advancedprivacy.domain.entities.TrackerMode
 import foundation.e.advancedprivacy.features.dashboard.DashboardFragmentArgs
@@ -45,7 +45,7 @@ data class State(
     val quickPrivacyState: QuickPrivacyState = QuickPrivacyState.DISABLED,
     val trackerMode: TrackerMode = TrackerMode.VULNERABLE,
     val isLocationHidden: Boolean = false,
-    val ipScramblingMode: FeatureServiceState = FeatureServiceState.STOPPING,
+    val ipScramblingMode: FeatureState = FeatureState.STOPPING,
     val dayStatistics: List<Pair<Int, Int>> = emptyList(),
     val activeTrackersCount: Int = 0,
 )
@@ -157,7 +157,7 @@ fun render(
         setTextViewText(
             R.id.state_ip_address,
             context.getString(
-                if (state.ipScramblingMode == FeatureServiceState.ON) R.string.widget_state_ipaddress_on
+                if (state.ipScramblingMode == FeatureState.ON) R.string.widget_state_ipaddress_on
                 else R.string.widget_state_ipaddress_off
             )
         )
-- 
cgit v1.2.1