diff --git a/app/build.gradle b/app/build.gradle
index fb731f89dac185547a3f55f56213d0ef1c8f6cfa..6fc16b30f80ca44c795f1bd1a0feab7494ec9c69 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -51,7 +51,6 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [
- persistent: "false",
mainActivityIntentFilterCategory: "android.intent.category.LAUNCHER"
]
@@ -89,7 +88,6 @@ android {
dimension 'os'
applicationIdSuffix '.standalone'
manifestPlaceholders = [
- persistent: "false",
mainActivityIntentFilterCategory: "android.intent.category.LAUNCHER"
]
@@ -112,7 +110,6 @@ android {
}
release {
manifestPlaceholders = [
- persistent: "true",
mainActivityIntentFilterCategory: "android.intent.category.INFO"
]
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 90a5bbf14efb52633b7fcf5b82ae6b56dd067faa..508c2f5901c96fe1c4ef6fb79dcdc89ad8061f8e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,12 +39,13 @@
+
+
(CoroutineScope::class.java).launch {
+ initBackgroundSingletons()
}
+ }
+ private fun synchronousInitComponents() {
// Fix 3386 : Initialize OrbotSupervisor, to make sure all Orbot is waked up before
// OrbotService may be started by the system.
val orbotSupervisor = get(OrbotSupervisor::class.java)
- get(CoroutineScope::class.java).launch {
- initBackgroundSingletons()
- }
+ get(IpScramblingStateUseCase::class.java)
+ get(TrackersStateUseCase::class.java)
+ get(FakeLocationStateUseCase::class.java)
+ get(VpnSupervisorUseCase::class.java).listenSettings()
}
private suspend fun initBackgroundSingletons() = withContext(Dispatchers.IO) {
@@ -82,11 +97,6 @@ class AdvancedPrivacyApplication : Application() {
)
get(NotificationsPresenter::class.java).startListening()
-
- get(IpScramblingStateUseCase::class.java)
- get(TrackersStateUseCase::class.java)
- get(FakeLocationStateUseCase::class.java)
- get(VpnSupervisorUseCase::class.java).listenSettings()
get(WeeklyReportUseCase::class.java).listen()
}
}
diff --git a/privapp-permissions-foundation.e.advancedprivacy.xml b/privapp-permissions-foundation.e.advancedprivacy.xml
index 7edaacee198ba9064a4dc36705251db3218c737d..29b2c3eec87ac0390150ca84c453658b30204ad5 100644
--- a/privapp-permissions-foundation.e.advancedprivacy.xml
+++ b/privapp-permissions-foundation.e.advancedprivacy.xml
@@ -6,5 +6,6 @@
+
-
\ No newline at end of file
+
diff --git a/trackersserviceeos/build.gradle b/trackersserviceeos/build.gradle
index 6d67b5822b606f9d359a5a6164b45fcac36d5028..30d35648806db6d11302971e76277ac9839f12d0 100644
--- a/trackersserviceeos/build.gradle
+++ b/trackersserviceeos/build.gradle
@@ -34,6 +34,7 @@ dependencies {
implementation(
libs.androidx.core.ktx,
+ libs.androidx.work.ktx,
libs.bundles.koin,
libs.kotlinx.coroutines,
libs.pcap4j,
diff --git a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/StayAwakeWorker.kt b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/StayAwakeWorker.kt
new file mode 100644
index 0000000000000000000000000000000000000000..239febf12179a8ff5b754a756432d68c8f40cee5
--- /dev/null
+++ b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/StayAwakeWorker.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2025 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.service
+
+import android.content.Context
+import androidx.work.CoroutineWorker
+import androidx.work.WorkerParameters
+import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersSupervisor
+import org.koin.java.KoinJavaComponent
+import timber.log.Timber
+
+class StayAwakeWorker(
+ context: Context,
+ workerParams: WorkerParameters
+) : CoroutineWorker(context, workerParams) {
+ override suspend fun doWork(): Result {
+ return try {
+ val trackerSupervisor: TrackersSupervisorEos by KoinJavaComponent.inject(
+ TrackersSupervisor::class.java
+ )
+
+ trackerSupervisor.wakeUpService()
+ Result.success()
+ } catch (e: Exception) {
+ Timber.w(e, "Can't Wakeup tracker service")
+ Result.failure()
+ }
+ }
+}
diff --git a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt
index 5f573b0fa9d5d4fa8e3e283870e4e3cd24ead7e6..f38699dd5af357d970a59d57ec14f74f7abadde9 100644
--- a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt
+++ b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersService.kt
@@ -22,24 +22,40 @@ import android.content.Intent
import android.os.IBinder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import org.koin.java.KoinJavaComponent.get
class TrackersService : Service() {
companion object {
const val ACTION_START = "foundation.e.privacymodules.trackers.intent.action.START"
+ const val ACTION_RESTART = "foundation.e.privacymodules.trackers.intent.action.RESTART"
var coroutineScope = CoroutineScope(Dispatchers.IO)
}
+ private var writeLogJob: Job? = null
+ private var listenJob: Job? = null
+
override fun onBind(intent: Intent): IBinder? {
throw UnsupportedOperationException("Not yet implemented")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- if (ACTION_START == intent?.action) {
- stop()
- start()
+ when (intent?.action) {
+ ACTION_START -> {
+ if (writeLogJob?.isActive != true ||
+ listenJob?.isActive != true
+ ) {
+ stop()
+ start()
+ }
+ }
+
+ ACTION_RESTART -> {
+ stop()
+ start()
+ }
}
return START_REDELIVER_INTENT
}
@@ -47,8 +63,8 @@ class TrackersService : Service() {
private fun start() {
coroutineScope = CoroutineScope(Dispatchers.IO)
get(DNSBlocker::class.java).apply {
- filterHostnameUseCase.writeLogJob(coroutineScope)
- listenJob(coroutineScope)
+ writeLogJob = filterHostnameUseCase.writeLogJob(coroutineScope)
+ listenJob = listenJob(coroutineScope)
}
}
diff --git a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersSupervisorEos.kt b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersSupervisorEos.kt
index 4580389acc77e9725ced5d956144bf100011e25b..f6bd3c5284a17a915399ae727cd656c8e6627ce4 100644
--- a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersSupervisorEos.kt
+++ b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/TrackersSupervisorEos.kt
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2025 E FOUNDATION
* Copyright (C) 2023 MURENA SAS
*
* This program is free software: you can redistribute it and/or modify
@@ -18,10 +19,14 @@ package foundation.e.advancedprivacy.trackers.service
import android.content.Context
import android.content.Intent
+import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.PeriodicWorkRequestBuilder
+import androidx.work.WorkManager
import foundation.e.advancedprivacy.domain.entities.FeatureState
import foundation.e.advancedprivacy.domain.usecases.VpnSupervisorUseCase
import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersSupervisor
import foundation.e.advancedprivacy.trackers.service.TrackersService.Companion.ACTION_START
+import java.time.Duration
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.isActive
@@ -32,10 +37,23 @@ import org.koin.core.qualifier.named
import org.koin.dsl.module
class TrackersSupervisorEos(private val context: Context) : TrackersSupervisor {
+ companion object {
+ private const val STAYAWAKE_WORKER_TAG = "STAYAWAKE_WORKER"
+ private const val STAYAWAKE_PERIOD_IN_MINUTES = 15L
+ }
override val state: StateFlow = MutableStateFlow(FeatureState.ON)
override fun start(): Boolean {
+ startStayAwayWorker()
+ return startService()
+ }
+
+ fun wakeUpService(): Boolean {
+ return startService()
+ }
+
+ private fun startService(): Boolean {
val intent = Intent(context, TrackersService::class.java)
intent.action = ACTION_START
return context.startService(intent) != null
@@ -50,6 +68,13 @@ class TrackersSupervisorEos(private val context: Context) : TrackersSupervisor {
}
override val dnsFilterForIpScrambling = null
+
+ private fun startStayAwayWorker() {
+ val workRequest = PeriodicWorkRequestBuilder(Duration.ofMinutes(STAYAWAKE_PERIOD_IN_MINUTES))
+ .addTag(STAYAWAKE_WORKER_TAG).build()
+
+ WorkManager.getInstance(context).enqueueUniquePeriodicWork(STAYAWAKE_WORKER_TAG, ExistingPeriodicWorkPolicy.REPLACE, workRequest)
+ }
}
val trackerServiceModule = module {
diff --git a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt
index 510c0499447240ce2c3a9d2750c19592ebb346bd..8b2a9117a0fd928c7059dfa416d115c2f0594d57 100644
--- a/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt
+++ b/trackersserviceeos/src/main/java/foundation/e/advancedprivacy/trackers/service/VpnSupervisorUseCaseEos.kt
@@ -30,6 +30,7 @@ import foundation.e.advancedprivacy.ipscrambler.OrbotSupervisor
import foundation.e.advancedprivacy.trackers.domain.externalinterfaces.TrackersSupervisor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -44,16 +45,21 @@ class VpnSupervisorUseCaseEos(
private val scope: CoroutineScope
) : VpnSupervisorUseCase {
+ private var listenIpscramblingJob: Job? = null
+ private var listenDisclaimerJob: Job? = null
+
override fun listenSettings() {
trackersSupervisor.start()
- scope.launch(Dispatchers.IO) {
+ listenIpscramblingJob?.cancel()
+ listenIpscramblingJob = scope.launch(Dispatchers.IO) {
localStateRepository.ipScramblingEnabled.collect {
applySettings(it)
}
}
- scope.launch(Dispatchers.IO) {
+ listenDisclaimerJob?.cancel()
+ listenDisclaimerJob = scope.launch(Dispatchers.IO) {
localStateRepository.blockTrackers.drop(1).filter { it }.collect {
localStateRepository.emitStartVpnDisclaimer(TrackersControl())
}