mirror of
https://github.com/wgtunnel/android.git
synced 2026-07-03 14:07:49 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23d75ff0b7 | |||
| 11efad703c | |||
| b81f43c7cf | |||
| 68865843dc | |||
| 62daf138dd | |||
| 1120a8fc81 | |||
| ab10be7266 | |||
| 88f9d43e51 | |||
| 2877757396 | |||
| c657c62640 | |||
| d84d9df57d |
@@ -73,7 +73,6 @@ class WireGuardAutoTunnel : Application() {
|
||||
if (!settingsRepository.getSettings().isKernelEnabled) {
|
||||
tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList())
|
||||
}
|
||||
|
||||
appStateRepository.getLocale()?.let {
|
||||
LocaleUtil.changeLocale(it)
|
||||
}
|
||||
|
||||
+4
-3
@@ -3,6 +3,7 @@ package com.zaneschepke.wireguardautotunnel.service.foreground
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
|
||||
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
|
||||
import com.zaneschepke.wireguardautotunnel.service.foreground.autotunnel.AutoTunnelService
|
||||
import com.zaneschepke.wireguardautotunnel.service.tile.AutoTunnelControlTile
|
||||
@@ -58,12 +59,12 @@ class ServiceManager
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun startBackgroundService() {
|
||||
suspend fun startBackgroundService(tunnelConfig: TunnelConfig?) {
|
||||
if (backgroundService.isCompleted) return
|
||||
kotlin.runCatching {
|
||||
startService(TunnelBackgroundService::class.java, true)
|
||||
backgroundService.await()
|
||||
backgroundService.getCompleted().start()
|
||||
backgroundService.getCompleted().start(tunnelConfig)
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
}
|
||||
@@ -85,7 +86,7 @@ class ServiceManager
|
||||
}
|
||||
}
|
||||
|
||||
fun updateAutoTunnelTile() {
|
||||
private fun updateAutoTunnelTile() {
|
||||
if (autoTunnelTile.isCompleted) {
|
||||
autoTunnelTile.getCompleted().updateTileState()
|
||||
} else {
|
||||
|
||||
+10
-7
@@ -6,6 +6,8 @@ import android.os.IBinder
|
||||
import androidx.core.app.ServiceCompat
|
||||
import androidx.lifecycle.LifecycleService
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
|
||||
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationAction
|
||||
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
|
||||
import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
|
||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||
@@ -24,12 +26,11 @@ class TunnelBackgroundService : LifecycleService() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
start()
|
||||
serviceManager.backgroundService.complete(this)
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
super.onBind(intent)
|
||||
// We don't provide binding, so return null
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -38,11 +39,11 @@ class TunnelBackgroundService : LifecycleService() {
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
fun start() {
|
||||
fun start(tunnelConfig: TunnelConfig?) {
|
||||
ServiceCompat.startForeground(
|
||||
this,
|
||||
NotificationService.KERNEL_SERVICE_NOTIFICATION_ID,
|
||||
createNotification(),
|
||||
createNotification(tunnelConfig),
|
||||
Constants.SYSTEM_EXEMPT_SERVICE_TYPE_ID,
|
||||
)
|
||||
}
|
||||
@@ -57,11 +58,13 @@ class TunnelBackgroundService : LifecycleService() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun createNotification(): Notification {
|
||||
private fun createNotification(tunnelConfig: TunnelConfig?): Notification {
|
||||
return notificationService.createNotification(
|
||||
WireGuardNotification.NotificationChannels.VPN,
|
||||
getString(R.string.tunnel_running),
|
||||
description = "",
|
||||
title = "${getString(R.string.tunnel_running)} - ${tunnelConfig?.name}",
|
||||
actions = listOf(
|
||||
notificationService.createNotificationAction(NotificationAction.TUNNEL_OFF),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -86,13 +86,13 @@ constructor(
|
||||
|
||||
fun NotificationChannels.asBuilder(): NotificationCompat.Builder {
|
||||
return when (this) {
|
||||
NotificationChannels.VPN -> {
|
||||
NotificationChannels.AUTO_TUNNEL -> {
|
||||
NotificationCompat.Builder(
|
||||
context,
|
||||
context.getString(R.string.auto_tunnel_channel_id),
|
||||
)
|
||||
}
|
||||
NotificationChannels.AUTO_TUNNEL -> {
|
||||
NotificationChannels.VPN -> {
|
||||
NotificationCompat.Builder(
|
||||
context,
|
||||
context.getString(R.string.vpn_channel_id),
|
||||
|
||||
+41
-43
@@ -102,6 +102,7 @@ constructor(
|
||||
else -> throw NotImplementedError()
|
||||
}
|
||||
}.onFailure {
|
||||
// TODO add better error message and comms to user
|
||||
Timber.e(it)
|
||||
}
|
||||
}
|
||||
@@ -113,26 +114,15 @@ constructor(
|
||||
}
|
||||
|
||||
override suspend fun startTunnel(tunnelConfig: TunnelConfig?, background: Boolean) {
|
||||
if (tunnelConfig == null) return
|
||||
withContext(ioDispatcher) {
|
||||
if (isTunnelAlreadyRunning(tunnelConfig)) return@withContext
|
||||
if (tunnelConfig == null || isTunnelAlreadyRunning(tunnelConfig)) return@withContext
|
||||
updateTunnelConfig(tunnelConfig) // need to update this here
|
||||
withServiceActive {
|
||||
onBeforeStart(background)
|
||||
onBeforeStart()
|
||||
tunnelControlMutex.withLock {
|
||||
setState(tunnelConfig, TunnelState.UP).onSuccess {
|
||||
startActiveTunnelJobs()
|
||||
if (it.isUp()) appDataRepository.tunnels.save(tunnelConfig.copy(isActive = true))
|
||||
with(notificationService) {
|
||||
val notification = createNotification(
|
||||
WireGuardNotification.NotificationChannels.VPN,
|
||||
title = "${context.getString(R.string.tunnel_running)} - ${tunnelConfig.name}",
|
||||
actions = listOf(
|
||||
notificationService.createNotificationAction(NotificationAction.TUNNEL_OFF),
|
||||
),
|
||||
)
|
||||
show(VPN_NOTIFICATION_ID, notification)
|
||||
}
|
||||
updateTunnelState(it, tunnelConfig)
|
||||
onTunnelStart(tunnelConfig)
|
||||
}
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
@@ -148,10 +138,8 @@ constructor(
|
||||
if (tunnelConfig == null) return@withContext
|
||||
tunnelControlMutex.withLock {
|
||||
setState(tunnelConfig, TunnelState.DOWN).onSuccess {
|
||||
onTunnelStop(tunnelConfig)
|
||||
updateTunnelState(it, null)
|
||||
onStop(tunnelConfig)
|
||||
notificationService.remove(VPN_NOTIFICATION_ID)
|
||||
stopBackgroundService()
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
}
|
||||
@@ -216,33 +204,45 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun shutDownActiveTunnel() {
|
||||
private suspend fun onBeforeStart() {
|
||||
with(_vpnState.value) {
|
||||
if (status.isUp()) {
|
||||
stopTunnel()
|
||||
}
|
||||
if (status.isUp()) stopTunnel() else clearJobsAndStats()
|
||||
if (isKernelBackend == true) serviceManager.startBackgroundService(tunnelConfig)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun startBackgroundService() {
|
||||
serviceManager.startBackgroundService()
|
||||
serviceManager.updateTunnelTile()
|
||||
private suspend fun onTunnelStart(tunnelConfig: TunnelConfig) {
|
||||
startActiveTunnelJobs()
|
||||
if (_vpnState.value.status.isUp()) {
|
||||
appDataRepository.tunnels.save(tunnelConfig.copy(isActive = true))
|
||||
}
|
||||
if (isKernelBackend == false) launchUserspaceTunnelNotification()
|
||||
}
|
||||
|
||||
private fun stopBackgroundService() {
|
||||
serviceManager.stopBackgroundService()
|
||||
serviceManager.updateTunnelTile()
|
||||
private fun launchUserspaceTunnelNotification() {
|
||||
with(notificationService) {
|
||||
val notification = createNotification(
|
||||
WireGuardNotification.NotificationChannels.VPN,
|
||||
title = "${context.getString(R.string.tunnel_running)} - ${_vpnState.value.tunnelConfig?.name}",
|
||||
actions = listOf(
|
||||
notificationService.createNotificationAction(NotificationAction.TUNNEL_OFF),
|
||||
),
|
||||
)
|
||||
show(VPN_NOTIFICATION_ID, notification)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onBeforeStart(background: Boolean) {
|
||||
shutDownActiveTunnel()
|
||||
resetBackendStatistics()
|
||||
val settings = appDataRepository.settings.getSettings()
|
||||
if (background || settings.isKernelEnabled) startBackgroundService()
|
||||
}
|
||||
|
||||
private suspend fun onStop(tunnelConfig: TunnelConfig) {
|
||||
private suspend fun onTunnelStop(tunnelConfig: TunnelConfig) {
|
||||
appDataRepository.tunnels.save(tunnelConfig.copy(isActive = false))
|
||||
if (isKernelBackend == true) {
|
||||
serviceManager.stopBackgroundService()
|
||||
} else {
|
||||
notificationService.remove(VPN_NOTIFICATION_ID)
|
||||
}
|
||||
clearJobsAndStats()
|
||||
}
|
||||
|
||||
private fun clearJobsAndStats() {
|
||||
cancelActiveTunnelJobs()
|
||||
resetBackendStatistics()
|
||||
}
|
||||
@@ -301,13 +301,11 @@ constructor(
|
||||
is Backend -> updateBackendStatistics(
|
||||
WireGuardStatistics(backend.getStatistics(this@WireGuardTunnel)),
|
||||
)
|
||||
is org.amnezia.awg.backend.Backend -> {
|
||||
updateBackendStatistics(
|
||||
AmneziaStatistics(
|
||||
backend.getStatistics(this@WireGuardTunnel),
|
||||
),
|
||||
)
|
||||
}
|
||||
is org.amnezia.awg.backend.Backend -> updateBackendStatistics(
|
||||
AmneziaStatistics(
|
||||
backend.getStatistics(this@WireGuardTunnel),
|
||||
),
|
||||
)
|
||||
}
|
||||
delay(VPN_STATISTIC_CHECK_INTERVAL)
|
||||
}
|
||||
|
||||
@@ -237,6 +237,7 @@ constructor(
|
||||
if (!isKernelEnabled) {
|
||||
requestRoot().onSuccess {
|
||||
if (!isKernelSupported()) return@onSuccess SnackbarController.showMessage(StringValue.StringResource(R.string.kernel_not_supported))
|
||||
tunnelService.get().setBackendState(BackendState.INACTIVE, emptyList())
|
||||
appDataRepository.settings.save(
|
||||
copy(
|
||||
isKernelEnabled = true,
|
||||
|
||||
+42
-41
@@ -151,50 +151,51 @@ fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel(), appViewModel:
|
||||
),
|
||||
)
|
||||
if (!isRunningOnTv) {
|
||||
addAll(
|
||||
listOf(
|
||||
SelectionItem(
|
||||
Icons.Outlined.VpnLock,
|
||||
{
|
||||
ScaledSwitch(
|
||||
enabled = !(
|
||||
(
|
||||
uiState.settings.isTunnelOnWifiEnabled ||
|
||||
uiState.settings.isTunnelOnEthernetEnabled ||
|
||||
uiState.settings.isTunnelOnMobileDataEnabled
|
||||
) &&
|
||||
uiState.settings.isAutoTunnelEnabled
|
||||
),
|
||||
onClick = { appViewModel.onToggleAlwaysOnVPN() },
|
||||
checked = uiState.settings.isAlwaysOnVpnEnabled,
|
||||
)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.always_on_vpn_support),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
},
|
||||
onClick = { appViewModel.onToggleAlwaysOnVPN() },
|
||||
),
|
||||
SelectionItem(
|
||||
Icons.Outlined.VpnKeyOff,
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.kill_switch_options),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
navController.navigate(Route.KillSwitch)
|
||||
},
|
||||
trailing = {
|
||||
ForwardButton { navController.navigate(Route.KillSwitch) }
|
||||
},
|
||||
),
|
||||
add(
|
||||
SelectionItem(
|
||||
Icons.Outlined.VpnLock,
|
||||
{
|
||||
ScaledSwitch(
|
||||
enabled = !(
|
||||
(
|
||||
uiState.settings.isTunnelOnWifiEnabled ||
|
||||
uiState.settings.isTunnelOnEthernetEnabled ||
|
||||
uiState.settings.isTunnelOnMobileDataEnabled
|
||||
) &&
|
||||
uiState.settings.isAutoTunnelEnabled
|
||||
),
|
||||
onClick = { appViewModel.onToggleAlwaysOnVPN() },
|
||||
checked = uiState.settings.isAlwaysOnVpnEnabled,
|
||||
)
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.always_on_vpn_support),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
},
|
||||
onClick = { appViewModel.onToggleAlwaysOnVPN() },
|
||||
),
|
||||
)
|
||||
}
|
||||
add(
|
||||
SelectionItem(
|
||||
Icons.Outlined.VpnKeyOff,
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.kill_switch_options),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
navController.navigate(Route.KillSwitch)
|
||||
},
|
||||
trailing = {
|
||||
ForwardButton { navController.navigate(Route.KillSwitch) }
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
add(
|
||||
SelectionItem(
|
||||
Icons.Outlined.Restore,
|
||||
|
||||
+23
-16
@@ -25,7 +25,10 @@ import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SelectionIte
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SurfaceSelectionGroupButton
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.permission.vpn.withVpnPermission
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.SnackbarController
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.components.ForwardButton
|
||||
import com.zaneschepke.wireguardautotunnel.util.StringValue
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.isRunningOnTv
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.launchVpnSettings
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
|
||||
@@ -38,6 +41,8 @@ fun KillSwitchScreen(uiState: AppUiState, appViewModel: AppViewModel) {
|
||||
|
||||
fun toggleVpnKillSwitch() {
|
||||
with(uiState.settings) {
|
||||
// TODO improve this error message
|
||||
if (isKernelEnabled) return SnackbarController.showMessage(StringValue.StringResource(R.string.kernel_not_supported))
|
||||
if (isVpnKillSwitchEnabled) {
|
||||
appViewModel.onToggleVpnKillSwitch(false)
|
||||
} else {
|
||||
@@ -66,23 +71,25 @@ fun KillSwitchScreen(uiState: AppUiState, appViewModel: AppViewModel) {
|
||||
.padding(top = 24.dp.scaledHeight())
|
||||
.padding(horizontal = 24.dp.scaledWidth()),
|
||||
) {
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(
|
||||
SelectionItem(
|
||||
Icons.Outlined.AdminPanelSettings,
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.native_kill_switch),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
},
|
||||
onClick = { context.launchVpnSettings() },
|
||||
trailing = {
|
||||
ForwardButton { context.launchVpnSettings() }
|
||||
},
|
||||
if (!context.isRunningOnTv()) {
|
||||
SurfaceSelectionGroupButton(
|
||||
listOf(
|
||||
SelectionItem(
|
||||
Icons.Outlined.AdminPanelSettings,
|
||||
title = {
|
||||
Text(
|
||||
stringResource(R.string.native_kill_switch),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
|
||||
)
|
||||
},
|
||||
onClick = { context.launchVpnSettings() },
|
||||
trailing = {
|
||||
ForwardButton { context.launchVpnSettings() }
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
SurfaceSelectionGroupButton(
|
||||
buildList {
|
||||
add(
|
||||
|
||||
+2
-2
@@ -84,8 +84,8 @@ fun Config.toWgQuickString(): String {
|
||||
|
||||
fun RootShell.getCurrentWifiName(): String? {
|
||||
val response = mutableListOf<String>()
|
||||
this.run(response, "dumpsys wifi | grep -o \"SSID: [^,]*\" | cut -d ' ' -f2- | tr -d '\"'")
|
||||
return response.lastOrNull()
|
||||
this.run(response, "dumpsys wifi | grep 'Supplicant state: COMPLETED' | grep -o 'SSID: [^,]*' | cut -d ' ' -f2- | tr -d '\"'")
|
||||
return response.firstOrNull()
|
||||
}
|
||||
|
||||
fun Backend.BackendState.asBackendState(): BackendState {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
object Constants {
|
||||
const val VERSION_NAME = "3.6.3"
|
||||
const val VERSION_NAME = "3.6.4"
|
||||
const val JVM_TARGET = "17"
|
||||
const val VERSION_CODE = 36300
|
||||
const val VERSION_CODE = 36400
|
||||
const val TARGET_SDK = 35
|
||||
const val MIN_SDK = 26
|
||||
const val APP_ID = "com.zaneschepke.wireguardautotunnel"
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
What's new:
|
||||
- Fixed kernel mode toggle bug
|
||||
- Fixed notification crash bug
|
||||
@@ -16,16 +16,16 @@ junit = "4.13.2"
|
||||
kotlinx-serialization-json = "1.7.3"
|
||||
lifecycle-runtime-compose = "2.8.7"
|
||||
material3 = "1.3.1"
|
||||
navigationCompose = "2.8.4"
|
||||
navigationCompose = "2.8.5"
|
||||
pinLockCompose = "1.0.4"
|
||||
roomVersion = "2.6.1"
|
||||
timber = "5.0.1"
|
||||
tunnel = "1.2.1"
|
||||
androidGradlePlugin = "8.8.0-rc01"
|
||||
androidGradlePlugin = "8.9.0-alpha06"
|
||||
kotlin = "2.1.0"
|
||||
ksp = "2.1.0-1.0.29"
|
||||
composeBom = "2024.11.00"
|
||||
compose = "1.7.5"
|
||||
composeBom = "2024.12.01"
|
||||
compose = "1.7.6"
|
||||
zxingAndroidEmbedded = "4.3.0"
|
||||
coreSplashscreen = "1.0.1"
|
||||
gradlePlugins-grgit = "5.3.0"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
13
|
||||
16
|
||||
Reference in New Issue
Block a user