fix: add action and tunnel name to kernel notification (#490)
This commit is contained in:
parent
1120a8fc81
commit
62daf138dd
|
@ -73,7 +73,6 @@ class WireGuardAutoTunnel : Application() {
|
||||||
if (!settingsRepository.getSettings().isKernelEnabled) {
|
if (!settingsRepository.getSettings().isKernelEnabled) {
|
||||||
tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList())
|
tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
appStateRepository.getLocale()?.let {
|
appStateRepository.getLocale()?.let {
|
||||||
LocaleUtil.changeLocale(it)
|
LocaleUtil.changeLocale(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.zaneschepke.wireguardautotunnel.service.foreground
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import com.zaneschepke.wireguardautotunnel.data.domain.TunnelConfig
|
||||||
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
|
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.autotunnel.AutoTunnelService
|
import com.zaneschepke.wireguardautotunnel.service.foreground.autotunnel.AutoTunnelService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tile.AutoTunnelControlTile
|
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
|
if (backgroundService.isCompleted) return
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
startService(TunnelBackgroundService::class.java, true)
|
startService(TunnelBackgroundService::class.java, true)
|
||||||
backgroundService.await()
|
backgroundService.await()
|
||||||
backgroundService.getCompleted().start()
|
backgroundService.getCompleted().start(tunnelConfig)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
Timber.e(it)
|
Timber.e(it)
|
||||||
}
|
}
|
||||||
|
@ -85,7 +86,7 @@ class ServiceManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateAutoTunnelTile() {
|
private fun updateAutoTunnelTile() {
|
||||||
if (autoTunnelTile.isCompleted) {
|
if (autoTunnelTile.isCompleted) {
|
||||||
autoTunnelTile.getCompleted().updateTileState()
|
autoTunnelTile.getCompleted().updateTileState()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import android.os.IBinder
|
||||||
import androidx.core.app.ServiceCompat
|
import androidx.core.app.ServiceCompat
|
||||||
import androidx.lifecycle.LifecycleService
|
import androidx.lifecycle.LifecycleService
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
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.NotificationService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
|
import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
|
||||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||||
|
@ -24,12 +26,11 @@ class TunnelBackgroundService : LifecycleService() {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
start()
|
serviceManager.backgroundService.complete(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? {
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
super.onBind(intent)
|
super.onBind(intent)
|
||||||
// We don't provide binding, so return null
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,11 +39,11 @@ class TunnelBackgroundService : LifecycleService() {
|
||||||
return super.onStartCommand(intent, flags, startId)
|
return super.onStartCommand(intent, flags, startId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun start() {
|
fun start(tunnelConfig: TunnelConfig?) {
|
||||||
ServiceCompat.startForeground(
|
ServiceCompat.startForeground(
|
||||||
this,
|
this,
|
||||||
NotificationService.KERNEL_SERVICE_NOTIFICATION_ID,
|
NotificationService.KERNEL_SERVICE_NOTIFICATION_ID,
|
||||||
createNotification(),
|
createNotification(tunnelConfig),
|
||||||
Constants.SYSTEM_EXEMPT_SERVICE_TYPE_ID,
|
Constants.SYSTEM_EXEMPT_SERVICE_TYPE_ID,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -57,11 +58,13 @@ class TunnelBackgroundService : LifecycleService() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNotification(): Notification {
|
private fun createNotification(tunnelConfig: TunnelConfig?): Notification {
|
||||||
return notificationService.createNotification(
|
return notificationService.createNotification(
|
||||||
WireGuardNotification.NotificationChannels.VPN,
|
WireGuardNotification.NotificationChannels.VPN,
|
||||||
getString(R.string.tunnel_running),
|
title = "${getString(R.string.tunnel_running)} - ${tunnelConfig?.name}",
|
||||||
description = "",
|
actions = listOf(
|
||||||
|
notificationService.createNotificationAction(NotificationAction.TUNNEL_OFF),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,6 @@ constructor(
|
||||||
|
|
||||||
private suspend fun setState(tunnelConfig: TunnelConfig, tunnelState: TunnelState): Result<TunnelState> {
|
private suspend fun setState(tunnelConfig: TunnelConfig, tunnelState: TunnelState): Result<TunnelState> {
|
||||||
return runCatching {
|
return runCatching {
|
||||||
updateTunnelConfig(tunnelConfig) //need so kernel can get tunnel name or it breaks kernel
|
|
||||||
when (val backend = backend()) {
|
when (val backend = backend()) {
|
||||||
is Backend -> backend.setState(this, tunnelState.toWgState(), TunnelConfig.configFromWgQuick(tunnelConfig.wgQuick)).let { TunnelState.from(it) }
|
is Backend -> backend.setState(this, tunnelState.toWgState(), TunnelConfig.configFromWgQuick(tunnelConfig.wgQuick)).let { TunnelState.from(it) }
|
||||||
is org.amnezia.awg.backend.Backend -> {
|
is org.amnezia.awg.backend.Backend -> {
|
||||||
|
@ -103,7 +102,7 @@ constructor(
|
||||||
else -> throw NotImplementedError()
|
else -> throw NotImplementedError()
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
//TODO add better error message and comms to user
|
// TODO add better error message and comms to user
|
||||||
Timber.e(it)
|
Timber.e(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,26 +114,15 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun startTunnel(tunnelConfig: TunnelConfig?, background: Boolean) {
|
override suspend fun startTunnel(tunnelConfig: TunnelConfig?, background: Boolean) {
|
||||||
if (tunnelConfig == null) return
|
|
||||||
withContext(ioDispatcher) {
|
withContext(ioDispatcher) {
|
||||||
if (isTunnelAlreadyRunning(tunnelConfig)) return@withContext
|
if (tunnelConfig == null || isTunnelAlreadyRunning(tunnelConfig)) return@withContext
|
||||||
|
updateTunnelConfig(tunnelConfig) // need to update this here
|
||||||
withServiceActive {
|
withServiceActive {
|
||||||
onBeforeStart(background)
|
onBeforeStart()
|
||||||
tunnelControlMutex.withLock {
|
tunnelControlMutex.withLock {
|
||||||
setState(tunnelConfig, TunnelState.UP).onSuccess {
|
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)
|
updateTunnelState(it, tunnelConfig)
|
||||||
|
onTunnelStart(tunnelConfig)
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
Timber.e(it)
|
Timber.e(it)
|
||||||
|
@ -150,10 +138,8 @@ constructor(
|
||||||
if (tunnelConfig == null) return@withContext
|
if (tunnelConfig == null) return@withContext
|
||||||
tunnelControlMutex.withLock {
|
tunnelControlMutex.withLock {
|
||||||
setState(tunnelConfig, TunnelState.DOWN).onSuccess {
|
setState(tunnelConfig, TunnelState.DOWN).onSuccess {
|
||||||
|
onTunnelStop(tunnelConfig)
|
||||||
updateTunnelState(it, null)
|
updateTunnelState(it, null)
|
||||||
onStop(tunnelConfig)
|
|
||||||
notificationService.remove(VPN_NOTIFICATION_ID)
|
|
||||||
stopBackgroundService()
|
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
Timber.e(it)
|
Timber.e(it)
|
||||||
}
|
}
|
||||||
|
@ -218,33 +204,45 @@ constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun shutDownActiveTunnel() {
|
private suspend fun onBeforeStart() {
|
||||||
with(_vpnState.value) {
|
with(_vpnState.value) {
|
||||||
if (status.isUp()) {
|
if (status.isUp()) stopTunnel() else clearJobsAndStats()
|
||||||
stopTunnel()
|
if (isKernelBackend == true) serviceManager.startBackgroundService(tunnelConfig)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun startBackgroundService() {
|
private suspend fun onTunnelStart(tunnelConfig: TunnelConfig) {
|
||||||
serviceManager.startBackgroundService()
|
startActiveTunnelJobs()
|
||||||
serviceManager.updateTunnelTile()
|
if (_vpnState.value.status.isUp()) {
|
||||||
|
appDataRepository.tunnels.save(tunnelConfig.copy(isActive = true))
|
||||||
|
}
|
||||||
|
if (isKernelBackend == false) launchUserspaceTunnelNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopBackgroundService() {
|
private fun launchUserspaceTunnelNotification() {
|
||||||
serviceManager.stopBackgroundService()
|
with(notificationService) {
|
||||||
serviceManager.updateTunnelTile()
|
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) {
|
private suspend fun onTunnelStop(tunnelConfig: TunnelConfig) {
|
||||||
shutDownActiveTunnel()
|
|
||||||
resetBackendStatistics()
|
|
||||||
val settings = appDataRepository.settings.getSettings()
|
|
||||||
if (background || settings.isKernelEnabled) startBackgroundService()
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun onStop(tunnelConfig: TunnelConfig) {
|
|
||||||
appDataRepository.tunnels.save(tunnelConfig.copy(isActive = false))
|
appDataRepository.tunnels.save(tunnelConfig.copy(isActive = false))
|
||||||
|
if (isKernelBackend == true) {
|
||||||
|
serviceManager.stopBackgroundService()
|
||||||
|
} else {
|
||||||
|
notificationService.remove(VPN_NOTIFICATION_ID)
|
||||||
|
}
|
||||||
|
clearJobsAndStats()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearJobsAndStats() {
|
||||||
cancelActiveTunnelJobs()
|
cancelActiveTunnelJobs()
|
||||||
resetBackendStatistics()
|
resetBackendStatistics()
|
||||||
}
|
}
|
||||||
|
@ -303,14 +301,12 @@ constructor(
|
||||||
is Backend -> updateBackendStatistics(
|
is Backend -> updateBackendStatistics(
|
||||||
WireGuardStatistics(backend.getStatistics(this@WireGuardTunnel)),
|
WireGuardStatistics(backend.getStatistics(this@WireGuardTunnel)),
|
||||||
)
|
)
|
||||||
is org.amnezia.awg.backend.Backend -> {
|
is org.amnezia.awg.backend.Backend -> updateBackendStatistics(
|
||||||
updateBackendStatistics(
|
|
||||||
AmneziaStatistics(
|
AmneziaStatistics(
|
||||||
backend.getStatistics(this@WireGuardTunnel),
|
backend.getStatistics(this@WireGuardTunnel),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
delay(VPN_STATISTIC_CHECK_INTERVAL)
|
delay(VPN_STATISTIC_CHECK_INTERVAL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ fun KillSwitchScreen(uiState: AppUiState, appViewModel: AppViewModel) {
|
||||||
|
|
||||||
fun toggleVpnKillSwitch() {
|
fun toggleVpnKillSwitch() {
|
||||||
with(uiState.settings) {
|
with(uiState.settings) {
|
||||||
//TODO improve this error message
|
// TODO improve this error message
|
||||||
if(isKernelEnabled) return SnackbarController.showMessage(StringValue.StringResource(R.string.kernel_not_supported))
|
if (isKernelEnabled) return SnackbarController.showMessage(StringValue.StringResource(R.string.kernel_not_supported))
|
||||||
if (isVpnKillSwitchEnabled) {
|
if (isVpnKillSwitchEnabled) {
|
||||||
appViewModel.onToggleVpnKillSwitch(false)
|
appViewModel.onToggleVpnKillSwitch(false)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,7 +16,7 @@ junit = "4.13.2"
|
||||||
kotlinx-serialization-json = "1.7.3"
|
kotlinx-serialization-json = "1.7.3"
|
||||||
lifecycle-runtime-compose = "2.8.7"
|
lifecycle-runtime-compose = "2.8.7"
|
||||||
material3 = "1.3.1"
|
material3 = "1.3.1"
|
||||||
navigationCompose = "2.8.4"
|
navigationCompose = "2.8.5"
|
||||||
pinLockCompose = "1.0.4"
|
pinLockCompose = "1.0.4"
|
||||||
roomVersion = "2.6.1"
|
roomVersion = "2.6.1"
|
||||||
timber = "5.0.1"
|
timber = "5.0.1"
|
||||||
|
@ -24,8 +24,8 @@ tunnel = "1.2.1"
|
||||||
androidGradlePlugin = "8.8.0-rc01"
|
androidGradlePlugin = "8.8.0-rc01"
|
||||||
kotlin = "2.1.0"
|
kotlin = "2.1.0"
|
||||||
ksp = "2.1.0-1.0.29"
|
ksp = "2.1.0-1.0.29"
|
||||||
composeBom = "2024.11.00"
|
composeBom = "2024.12.01"
|
||||||
compose = "1.7.5"
|
compose = "1.7.6"
|
||||||
zxingAndroidEmbedded = "4.3.0"
|
zxingAndroidEmbedded = "4.3.0"
|
||||||
coreSplashscreen = "1.0.1"
|
coreSplashscreen = "1.0.1"
|
||||||
gradlePlugins-grgit = "5.3.0"
|
gradlePlugins-grgit = "5.3.0"
|
||||||
|
|
Loading…
Reference in New Issue