summaryrefslogtreecommitdiffhomepage
path: root/android/service/src
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson90@gmail.com>2023-12-18 12:12:17 +0100
committerJonathan <jonathan@mullvad.net>2023-12-21 13:33:59 +0100
commit8ed53a012b6c510a0dfd92925b8b0e742fd79da3 (patch)
treec92a6f524fa9f659a0edb2bb702e466d051ddba2 /android/service/src
parentc70509a345b6db8caf12c880b3ee3bf4c70bf79d (diff)
downloadmullvadvpn-8ed53a012b6c510a0dfd92925b8b0e742fd79da3.tar.xz
mullvadvpn-8ed53a012b6c510a0dfd92925b8b0e742fd79da3.zip
Support new tunnel state API in the Android frontend.
Remove `get_current_location` from jni.
Diffstat (limited to 'android/service/src')
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt11
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt2
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ConnectionProxy.kt2
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/LocationInfoCache.kt139
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt3
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/TunnelStateNotification.kt2
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ExponentialBackoff.kt52
7 files changed, 5 insertions, 206 deletions
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
index 0cfd0e1f7d..107f5d35fe 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt
@@ -10,7 +10,6 @@ import net.mullvad.mullvadvpn.model.DeviceEvent
import net.mullvad.mullvadvpn.model.DeviceListEvent
import net.mullvad.mullvadvpn.model.DeviceState
import net.mullvad.mullvadvpn.model.DnsOptions
-import net.mullvad.mullvadvpn.model.GeoIpLocation
import net.mullvad.mullvadvpn.model.GetAccountDataResult
import net.mullvad.mullvadvpn.model.LoginResult
import net.mullvad.mullvadvpn.model.ObfuscationSettings
@@ -34,7 +33,7 @@ class MullvadDaemon(
protected var daemonInterfaceAddress = 0L
val onSettingsChange = EventNotifier<Settings?>(null)
- var onTunnelStateChange = EventNotifier<TunnelState>(TunnelState.Disconnected)
+ var onTunnelStateChange = EventNotifier<TunnelState>(TunnelState.Disconnected())
var onAppVersionInfoChange: ((AppVersionInfo) -> Unit)? = null
var onRelayListChange: ((RelayList) -> Unit)? = null
@@ -58,7 +57,7 @@ class MullvadDaemon(
onSettingsChange.notify(getSettings())
- onTunnelStateChange.notify(getState() ?: TunnelState.Disconnected)
+ onTunnelStateChange.notify(getState() ?: TunnelState.Disconnected())
}
fun connect() {
@@ -85,10 +84,6 @@ class MullvadDaemon(
return getWwwAuthToken(daemonInterfaceAddress) ?: ""
}
- fun getCurrentLocation(): GeoIpLocation? {
- return getCurrentLocation(daemonInterfaceAddress)
- }
-
fun getCurrentVersion(): String? {
return getCurrentVersion(daemonInterfaceAddress)
}
@@ -229,8 +224,6 @@ class MullvadDaemon(
private external fun getWwwAuthToken(daemonInterfaceAddress: Long): String?
- private external fun getCurrentLocation(daemonInterfaceAddress: Long): GeoIpLocation?
-
private external fun getCurrentVersion(daemonInterfaceAddress: Long): String?
private external fun getRelayLocations(daemonInterfaceAddress: Long): RelayList?
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
index e714295d9c..b0c55540a6 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
@@ -189,7 +189,7 @@ class MullvadVpnService : TalpidVpnService() {
override fun onTaskRemoved(rootIntent: Intent?) {
connectionProxy.onStateChange.latestEvent.let { tunnelState ->
Log.d(TAG, "Task removed (tunnelState=$tunnelState)")
- if (tunnelState == TunnelState.Disconnected) {
+ if (tunnelState is TunnelState.Disconnected) {
notificationManager.cancelNotification()
stop()
}
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ConnectionProxy.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ConnectionProxy.kt
index a2c97a05bd..65a27c8f69 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ConnectionProxy.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ConnectionProxy.kt
@@ -20,7 +20,7 @@ class ConnectionProxy(val vpnPermission: VpnPermission, endpoint: ServiceEndpoin
private val commandChannel = spawnActor()
private val daemon = endpoint.intermittentDaemon
- private val initialState = TunnelState.Disconnected
+ private val initialState = TunnelState.Disconnected()
var onStateChange = EventNotifier<TunnelState>(initialState)
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/LocationInfoCache.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/LocationInfoCache.kt
deleted file mode 100644
index 2d06cc109f..0000000000
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/LocationInfoCache.kt
+++ /dev/null
@@ -1,139 +0,0 @@
-package net.mullvad.mullvadvpn.service.endpoint
-
-import kotlin.properties.Delegates.observable
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.ClosedReceiveChannelException
-import kotlinx.coroutines.channels.ReceiveChannel
-import kotlinx.coroutines.channels.actor
-import kotlinx.coroutines.channels.trySendBlocking
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flow
-import kotlinx.coroutines.flow.receiveAsFlow
-import net.mullvad.mullvadvpn.lib.common.util.toGeographicLocationConstraint
-import net.mullvad.mullvadvpn.lib.ipc.Event
-import net.mullvad.mullvadvpn.model.Constraint
-import net.mullvad.mullvadvpn.model.GeoIpLocation
-import net.mullvad.mullvadvpn.model.RelaySettings
-import net.mullvad.mullvadvpn.model.TunnelState
-import net.mullvad.mullvadvpn.service.util.ExponentialBackoff
-import net.mullvad.talpid.tunnel.ActionAfterDisconnect
-
-class LocationInfoCache(private val endpoint: ServiceEndpoint) {
-
- private val fetchRetryDelays =
- ExponentialBackoff().apply {
- scale = 50
- cap = 30 /* min */ * 60 /* s */ * 1000 /* ms */
- count = 17 // ceil(log2(cap / scale) + 1)
- }
-
- private val fetchRequestChannel = runFetcher()
-
- private val daemon
- get() = endpoint.intermittentDaemon
-
- private var lastKnownRealLocation: GeoIpLocation? = null
- private var selectedRelayLocation: GeoIpLocation? = null
-
- var location: GeoIpLocation? by
- observable(null) { _, _, newLocation -> endpoint.sendEvent(Event.NewLocation(newLocation)) }
-
- var state by
- observable<TunnelState>(TunnelState.Disconnected) { _, _, newState ->
- when (newState) {
- is TunnelState.Disconnected -> {
- location = lastKnownRealLocation
- fetchRequestChannel.trySendBlocking(RequestFetch.ForRealLocation)
- }
- is TunnelState.Connecting -> location = newState.location
- is TunnelState.Connected -> {
- location = newState.location
- fetchRequestChannel.trySendBlocking(RequestFetch.ForRelayLocation)
- }
- is TunnelState.Disconnecting -> {
- when (newState.actionAfterDisconnect) {
- ActionAfterDisconnect.Nothing -> location = lastKnownRealLocation
- ActionAfterDisconnect.Block -> location = null
- ActionAfterDisconnect.Reconnect -> {
- lastKnownRealLocation?.let { location = it }
- }
- }
- }
- is TunnelState.Error -> location = null
- }
- }
-
- init {
- endpoint.connectionProxy.onStateChange.subscribe(this) { newState -> state = newState }
-
- endpoint.connectivityListener.connectivityNotifier.subscribe(this) { isConnected ->
- if (isConnected && state is TunnelState.Disconnected) {
- fetchRequestChannel.trySendBlocking(RequestFetch.ForRealLocation)
- }
- }
-
- endpoint.settingsListener.relaySettingsNotifier.subscribe(this, ::updateSelectedLocation)
- }
-
- fun onDestroy() {
- endpoint.connectionProxy.onStateChange.unsubscribe(this)
- endpoint.connectivityListener.connectivityNotifier.unsubscribe(this)
- endpoint.settingsListener.relaySettingsNotifier.unsubscribe(this)
-
- fetchRequestChannel.close()
- }
-
- private fun runFetcher() =
- GlobalScope.actor<RequestFetch>(Dispatchers.Default, Channel.CONFLATED) {
- try {
- fetcherLoop(channel)
- } catch (exception: ClosedReceiveChannelException) {}
- }
-
- private suspend fun fetcherLoop(channel: ReceiveChannel<RequestFetch>) {
- channel
- .receiveAsFlow()
- .flatMapLatest(::fetchCurrentLocation)
- .collect(::handleFetchedLocation)
- }
-
- private fun fetchCurrentLocation(fetchType: RequestFetch) = flow {
- var newLocation = daemon.await().getCurrentLocation()
-
- fetchRetryDelays.reset()
-
- while (newLocation == null) {
- delay(fetchRetryDelays.next())
- newLocation = daemon.await().getCurrentLocation()
- }
-
- emit(Pair(newLocation, fetchType))
- }
-
- private suspend fun handleFetchedLocation(pairItem: Pair<GeoIpLocation, RequestFetch>) {
- val (newLocation, fetchType) = pairItem
-
- if (fetchType == RequestFetch.ForRealLocation) {
- lastKnownRealLocation = newLocation
- }
-
- location = newLocation
- }
-
- private fun updateSelectedLocation(relaySettings: RelaySettings?) {
- val settings = relaySettings as? RelaySettings.Normal
- val constraint = settings?.relayConstraints?.location as? Constraint.Only
-
- selectedRelayLocation = constraint?.value?.toGeographicLocationConstraint()?.location
- }
-
- companion object {
- private enum class RequestFetch {
- ForRealLocation,
- ForRelayLocation,
- }
- }
-}
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt
index 70e7807ff9..09fc73e5d3 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt
@@ -46,7 +46,6 @@ class ServiceEndpoint(
val appVersionInfoCache = AppVersionInfoCache(this)
val authTokenCache = AuthTokenCache(this)
val customDns = CustomDns(this)
- val locationInfoCache = LocationInfoCache(this)
val relayListListener = RelayListListener(this)
val splitTunneling = SplitTunneling(SplitTunnelingPersistence(context), this)
val voucherRedeemer = VoucherRedeemer(this, accountCache)
@@ -77,7 +76,6 @@ class ServiceEndpoint(
connectionProxy.onDestroy()
customDns.onDestroy()
deviceRepositoryBackend.onDestroy()
- locationInfoCache.onDestroy()
relayListListener.onDestroy()
settingsListener.onDestroy()
splitTunneling.onDestroy()
@@ -127,7 +125,6 @@ class ServiceEndpoint(
Event.TunnelStateChange(connectionProxy.state),
Event.AccountHistoryEvent(accountCache.onAccountHistoryChange.latestEvent),
Event.SettingsUpdate(settingsListener.settings),
- Event.NewLocation(locationInfoCache.location),
Event.SplitTunnelingUpdate(splitTunneling.onChange.latestEvent),
Event.CurrentVersion(appVersionInfoCache.currentVersion),
Event.AppVersionInfo(appVersionInfoCache.appVersionInfo),
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/TunnelStateNotification.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/TunnelStateNotification.kt
index 97bddc8608..ede083a2a1 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/TunnelStateNotification.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/TunnelStateNotification.kt
@@ -77,7 +77,7 @@ class TunnelStateNotification(val context: Context) {
var showAction by observable(false) { _, _, _ -> update() }
var tunnelState by
- observable<TunnelState>(TunnelState.Disconnected) { _, _, newState ->
+ observable<TunnelState>(TunnelState.Disconnected()) { _, _, newState ->
val isReconnecting = newState is TunnelState.Connecting && reconnecting
val shouldBeginReconnecting =
(newState as? TunnelState.Disconnecting)?.actionAfterDisconnect ==
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ExponentialBackoff.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ExponentialBackoff.kt
deleted file mode 100644
index 12e94a9241..0000000000
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ExponentialBackoff.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package net.mullvad.mullvadvpn.service.util
-
-// Calculates a series of delays that increase exponentially.
-//
-// The delays follow the formula:
-//
-// (base ^ retryAttempt) * scale
-//
-// but it is never larger than the specified cap value.
-class ExponentialBackoff : Iterator<Long> {
- private var unscaledValue = 1L
- private var current = 1L
-
- var iteration = 1
- private set
-
- var base = 2L
- var scale = 1000L
- var cap = Long.MAX_VALUE
- var count: Int? = null
-
- override fun hasNext(): Boolean {
- val maxIterations = count
-
- if (maxIterations != null) {
- return iteration < maxIterations
- } else {
- return true
- }
- }
-
- override fun next(): Long {
- iteration += 1
-
- if (current >= cap) {
- return cap
- } else {
- val value = current
-
- unscaledValue *= base
- current = Math.min(cap, scale * unscaledValue)
-
- return value
- }
- }
-
- fun reset() {
- unscaledValue = 1L
- current = 1L
- iteration = 1
- }
-}