diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt index e18c9e5..580c5d8 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt @@ -73,7 +73,6 @@ class WireGuardAutoTunnel : Application() { if (!settingsRepository.getSettings().isKernelEnabled) { tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList()) } - appStateRepository.getLocale()?.let { LocaleUtil.changeLocale(it) } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt index 4fd3089..911db46 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt @@ -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 { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt index 02e6dbe..575e292 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/TunnelBackgroundService.kt @@ -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), + ), ) } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt index 955bf16..47818b3 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt @@ -85,7 +85,6 @@ constructor( private suspend fun setState(tunnelConfig: TunnelConfig, tunnelState: TunnelState): Result { return runCatching { - updateTunnelConfig(tunnelConfig) //need so kernel can get tunnel name or it breaks kernel when (val backend = backend()) { is Backend -> backend.setState(this, tunnelState.toWgState(), TunnelConfig.configFromWgQuick(tunnelConfig.wgQuick)).let { TunnelState.from(it) } is org.amnezia.awg.backend.Backend -> { @@ -103,7 +102,7 @@ constructor( else -> throw NotImplementedError() } }.onFailure { - //TODO add better error message and comms to user + // TODO add better error message and comms to user Timber.e(it) } } @@ -115,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) @@ -150,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) } @@ -218,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() } @@ -303,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) } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/killswitch/KillSwitchScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/killswitch/KillSwitchScreen.kt index 39a29f7..5baa11a 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/killswitch/KillSwitchScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/killswitch/KillSwitchScreen.kt @@ -41,8 +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)) + // TODO improve this error message + if (isKernelEnabled) return SnackbarController.showMessage(StringValue.StringResource(R.string.kernel_not_supported)) if (isVpnKillSwitchEnabled) { appViewModel.onToggleVpnKillSwitch(false) } else { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0513ee1..b23dbe4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ 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" @@ -24,8 +24,8 @@ tunnel = "1.2.1" androidGradlePlugin = "8.8.0-rc01" 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"