mirror of
https://github.com/wgtunnel/android.git
synced 2026-07-03 14:07:49 +02:00
@@ -51,6 +51,13 @@ class WireGuardAutoTunnel : Application(), KoinComponent {
|
||||
|
||||
private val backend: Backend by inject()
|
||||
|
||||
private val alwaysOnCallback =
|
||||
object : VpnService.AlwaysOnCallback {
|
||||
override fun alwaysOnTriggered() {
|
||||
applicationScope.launch { tunnelCoordinator.startDefault() }
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(KoinViewModelScopeApi::class)
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
@@ -86,13 +93,7 @@ class WireGuardAutoTunnel : Application(), KoinComponent {
|
||||
Timber.plant(ReleaseTree())
|
||||
}
|
||||
|
||||
backend.setAlwaysOnCallback(
|
||||
object : VpnService.AlwaysOnCallback {
|
||||
override fun alwaysOnTriggered() {
|
||||
applicationScope.launch { tunnelCoordinator.startDefault() }
|
||||
}
|
||||
}
|
||||
)
|
||||
backend.setAlwaysOnCallback(alwaysOnCallback)
|
||||
|
||||
val dispatcher = get<TunnelEventDispatcher>()
|
||||
val coordinator = get<TunnelCoordinator>()
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.zaneschepke.tunnel.util.RootShellException
|
||||
import com.zaneschepke.tunnel.util.buildResolvedPeers
|
||||
import com.zaneschepke.tunnel.util.toHostMap
|
||||
import com.zaneschepke.wireguardautotunnel.parser.ActiveConfig
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -250,7 +249,7 @@ class TunnelBackend(
|
||||
}
|
||||
|
||||
override fun setAlwaysOnCallback(alwaysOnCallback: VpnService.AlwaysOnCallback) {
|
||||
ServiceHolder.alwaysOnCallback = WeakReference(alwaysOnCallback)
|
||||
ServiceHolder.alwaysOnCallback = alwaysOnCallback
|
||||
}
|
||||
|
||||
override suspend fun stop(id: Int): Result<Unit> = tunnelMutex.withLock {
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.zaneschepke.tunnel.ProxyBackend
|
||||
import com.zaneschepke.tunnel.util.BackendException
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -90,7 +89,7 @@ internal class ServiceHolder(val context: Context) {
|
||||
service.shutdown()
|
||||
withTimeoutOrNull(1_500L.milliseconds) { tunnelServiceFlow.first { it == null } }
|
||||
} finally {
|
||||
clearVpnService()
|
||||
clearTunnelService()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +109,6 @@ internal class ServiceHolder(val context: Context) {
|
||||
const val SPECIAL_USE_SERVICE_TYPE_ID = 1 shl 30
|
||||
const val DEFAULT_MTU = 1280
|
||||
// for consumer to set AOVPN callback
|
||||
var alwaysOnCallback: WeakReference<VpnService.AlwaysOnCallback>? = null
|
||||
var alwaysOnCallback: VpnService.AlwaysOnCallback? = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class TunnelService : LifecycleService() {
|
||||
(intent.component!!.packageName != packageName)
|
||||
) {
|
||||
Timber.d("TunnelService started by system")
|
||||
alwaysOnCallback?.get()?.alwaysOnTriggered()
|
||||
alwaysOnCallback?.alwaysOnTriggered()
|
||||
}
|
||||
|
||||
return START_STICKY
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.zaneschepke.tunnel.service
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.TrafficStats
|
||||
import android.os.Build
|
||||
@@ -81,15 +82,28 @@ class VpnService : android.net.VpnService(), KillSwitch, SocketProtector {
|
||||
|
||||
bootKeepaliveService()
|
||||
|
||||
// Service restarted by system or Always-on VPN started
|
||||
if (
|
||||
intent == null ||
|
||||
intent.component == null ||
|
||||
(intent.component!!.packageName != packageName)
|
||||
) {
|
||||
Timber.d("VpnService started by system (Always-On trigger)")
|
||||
alwaysOnCallback?.get()?.alwaysOnTriggered()
|
||||
// system recovery restart
|
||||
if (intent == null) {
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
val isUserLaunch = intent.getBooleanExtra(getUserLaunchExtraKey(this), false)
|
||||
|
||||
val platformSaysAlwaysOn =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
isAlwaysOn
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
val isAlwaysOnTrigger =
|
||||
!isUserLaunch && (intent.action == SERVICE_INTERFACE || platformSaysAlwaysOn)
|
||||
|
||||
if (isAlwaysOnTrigger) {
|
||||
Timber.d("VpnService started by system (Always-On trigger)")
|
||||
alwaysOnCallback?.alwaysOnTriggered()
|
||||
}
|
||||
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
@@ -330,6 +344,21 @@ class VpnService : android.net.VpnService(), KillSwitch, SocketProtector {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private fun getUserLaunchExtraKey(context: Context): String {
|
||||
return "${context.packageName}.EXTRA_IS_USER_LAUNCH"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun start(context: Context, serviceClass: Class<out VpnService>) {
|
||||
val intent =
|
||||
Intent(context, serviceClass).apply {
|
||||
action = SERVICE_INTERFACE
|
||||
putExtra(getUserLaunchExtraKey(context), true)
|
||||
}
|
||||
context.startService(intent)
|
||||
}
|
||||
|
||||
private const val LOCKDOWN_SESSION_NAME = "Lockdown"
|
||||
private const val LOCALHOST = "127.0.0.1"
|
||||
private const val IPV4_INTERFACE_ADDRESS = "10.0.0.1"
|
||||
|
||||
Reference in New Issue
Block a user