diff options
| author | David Göransson <david.goransson90@gmail.com> | 2023-12-18 12:12:17 +0100 |
|---|---|---|
| committer | Jonathan <jonathan@mullvad.net> | 2023-12-21 13:33:59 +0100 |
| commit | 8ed53a012b6c510a0dfd92925b8b0e742fd79da3 (patch) | |
| tree | c92a6f524fa9f659a0edb2bb702e466d051ddba2 /android/service/src | |
| parent | c70509a345b6db8caf12c880b3ee3bf4c70bf79d (diff) | |
| download | mullvadvpn-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')
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 - } -} |
