diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2021-03-23 10:40:40 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2021-03-23 10:40:40 -0300 |
| commit | 5013c84f3def678951df13e4e961291d3fceeb8a (patch) | |
| tree | 5180d8a6df0645d042717174ed6ae6f294e6f525 | |
| parent | b22e0df01ba6d94325ae0c2a59101ead3b35712c (diff) | |
| parent | 308c2f43626777a22a3d98e53806b25e94a67b48 (diff) | |
| download | mullvadvpn-5013c84f3def678951df13e4e961291d3fceeb8a.tar.xz mullvadvpn-5013c84f3def678951df13e4e961291d3fceeb8a.zip | |
Merge branch 'split-settings-listener'
26 files changed, 276 insertions, 130 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt index 4b73f9a878..eafe9f1493 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AppVersionInfoCache.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.model.AppVersionInfo import net.mullvad.mullvadvpn.service.MullvadDaemon -import net.mullvad.mullvadvpn.service.SettingsListener +import net.mullvad.mullvadvpn.ui.serviceconnection.SettingsListener class AppVersionInfoCache( val context: Context, @@ -54,8 +54,10 @@ class AppVersionInfoCache( private set init { - settingsListener.subscribe(this) { settings -> - showBetaReleases = settings.showBetaReleases + settingsListener.settingsNotifier.subscribe(this) { maybeSettings -> + maybeSettings?.let { settings -> + showBetaReleases = settings.showBetaReleases + } } } @@ -68,7 +70,7 @@ class AppVersionInfoCache( fun onDestroy() { setUpJob.cancel() - settingsListener.unsubscribe(this) + settingsListener.settingsNotifier.unsubscribe(this) daemon.onAppVersionInfoChange = null } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt index af60840cc9..fe8142ed7d 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt @@ -9,7 +9,7 @@ import net.mullvad.mullvadvpn.model.RelaySettings import net.mullvad.mullvadvpn.relaylist.RelayItem import net.mullvad.mullvadvpn.relaylist.RelayList import net.mullvad.mullvadvpn.service.MullvadDaemon -import net.mullvad.mullvadvpn.service.SettingsListener +import net.mullvad.mullvadvpn.ui.serviceconnection.SettingsListener class RelayListListener(val daemon: MullvadDaemon, val settingsListener: SettingsListener) { private val setUpJob = setUp() @@ -34,14 +34,14 @@ class RelayListListener(val daemon: MullvadDaemon, val settingsListener: Setting } init { - settingsListener.onRelaySettingsChange = { newRelaySettings -> + settingsListener.relaySettingsNotifier.subscribe(this) { newRelaySettings -> relaySettingsChanged(newRelaySettings) } } fun onDestroy() { setUpJob.cancel() - settingsListener.onRelaySettingsChange = null + settingsListener.relaySettingsNotifier.unsubscribe(this) daemon.onRelayListChange = null } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt index fa6aa22081..d9df17e9c7 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Event.kt @@ -3,6 +3,7 @@ package net.mullvad.mullvadvpn.ipc import android.os.Message as RawMessage import android.os.Parcelable import kotlinx.parcelize.Parcelize +import net.mullvad.mullvadvpn.model.Settings // Events that can be sent from the service sealed class Event : Message(), Parcelable { @@ -12,6 +13,9 @@ sealed class Event : Message(), Parcelable { @Parcelize object ListenerReady : Event(), Parcelable + @Parcelize + data class SettingsUpdate(val settings: Settings?) : Event(), Parcelable + companion object { private const val MESSAGE_KEY = "event" diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Constraint.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Constraint.kt index 6d20c95dde..55779fd720 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Constraint.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Constraint.kt @@ -1,6 +1,13 @@ package net.mullvad.mullvadvpn.model -sealed class Constraint<T>() { - class Any<T>() : Constraint<T>() - data class Only<T>(val value: T) : Constraint<T>() +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +sealed class Constraint<T>() : Parcelable { + @Parcelize + @Suppress("PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY") + class Any<T>() : Constraint<T>(), Parcelable + + @Parcelize + data class Only<T : Parcelable>(val value: T) : Constraint<T>(), Parcelable } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt index e4d7b75481..6cef280b61 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/DnsOptions.kt @@ -1,6 +1,9 @@ package net.mullvad.mullvadvpn.model +import android.os.Parcelable import java.net.InetAddress import java.util.ArrayList +import kotlinx.parcelize.Parcelize -data class DnsOptions(val custom: Boolean, val addresses: ArrayList<InetAddress>) +@Parcelize +data class DnsOptions(val custom: Boolean, val addresses: ArrayList<InetAddress>) : Parcelable diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/LocationConstraint.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/LocationConstraint.kt index d5eae8490f..998167468d 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/LocationConstraint.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/LocationConstraint.kt @@ -1,11 +1,18 @@ package net.mullvad.mullvadvpn.model -sealed class LocationConstraint(val code: Array<String>) { - data class Country(var countryCode: String) : LocationConstraint(arrayOf(countryCode)) +import android.os.Parcelable +import kotlinx.parcelize.Parcelize - data class City(var countryCode: String, var cityCode: String) : - LocationConstraint(arrayOf(countryCode, cityCode)) +sealed class LocationConstraint(val code: Array<String>) : Parcelable { + @Parcelize + data class Country(val countryCode: String) : + LocationConstraint(arrayOf(countryCode)), Parcelable - data class Hostname(var countryCode: String, var cityCode: String, var hostname: String) : - LocationConstraint(arrayOf(countryCode, cityCode, hostname)) + @Parcelize + data class City(val countryCode: String, val cityCode: String) : + LocationConstraint(arrayOf(countryCode, cityCode)), Parcelable + + @Parcelize + data class Hostname(val countryCode: String, val cityCode: String, val hostname: String) : + LocationConstraint(arrayOf(countryCode, cityCode, hostname)), Parcelable } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraints.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraints.kt index e4e6d6634e..cd36577dae 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraints.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraints.kt @@ -1,3 +1,7 @@ package net.mullvad.mullvadvpn.model -data class RelayConstraints(val location: Constraint<LocationConstraint>) +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class RelayConstraints(val location: Constraint<LocationConstraint>) : Parcelable diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt index f46bd63e67..e1e56c3c51 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt @@ -1,6 +1,12 @@ package net.mullvad.mullvadvpn.model -sealed class RelaySettings { - object CustomTunnelEndpoint : RelaySettings() - class Normal(var relayConstraints: RelayConstraints) : RelaySettings() +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +sealed class RelaySettings : Parcelable { + @Parcelize + object CustomTunnelEndpoint : RelaySettings(), Parcelable + + @Parcelize + class Normal(val relayConstraints: RelayConstraints) : RelaySettings(), Parcelable } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt index fbc295d8a0..03ef69c638 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Settings.kt @@ -1,10 +1,14 @@ package net.mullvad.mullvadvpn.model +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize data class Settings( - var accountToken: String?, - var relaySettings: RelaySettings, - var allowLan: Boolean, - var autoConnect: Boolean, - var tunnelOptions: TunnelOptions, - var showBetaReleases: Boolean -) + val accountToken: String?, + val relaySettings: RelaySettings, + val allowLan: Boolean, + val autoConnect: Boolean, + val tunnelOptions: TunnelOptions, + val showBetaReleases: Boolean +) : Parcelable diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt index 1a960e1396..944a98b0b8 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelOptions.kt @@ -1,3 +1,10 @@ package net.mullvad.mullvadvpn.model -data class TunnelOptions(val wireguard: WireguardTunnelOptions, val dnsOptions: DnsOptions) +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class TunnelOptions( + val wireguard: WireguardTunnelOptions, + val dnsOptions: DnsOptions +) : Parcelable diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/WireguardTunnelOptions.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/WireguardTunnelOptions.kt index f9b7b314d5..251571021a 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/WireguardTunnelOptions.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/WireguardTunnelOptions.kt @@ -1,5 +1,8 @@ package net.mullvad.mullvadvpn.model +import android.os.Parcelable +import kotlinx.parcelize.Parcelize import net.mullvad.talpid.net.wireguard.TunnelOptions as TalpidWireguardTunnelOptions -data class WireguardTunnelOptions(val options: TalpidWireguardTunnelOptions) +@Parcelize +data class WireguardTunnelOptions(val options: TalpidWireguardTunnelOptions) : Parcelable diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt index 7c10d4b822..5548b93b36 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/AccountCache.kt @@ -2,6 +2,7 @@ package net.mullvad.mullvadvpn.service import kotlinx.coroutines.delay import net.mullvad.mullvadvpn.model.GetAccountDataResult +import net.mullvad.mullvadvpn.service.endpoint.SettingsListener import net.mullvad.mullvadvpn.util.ExponentialBackoff import net.mullvad.mullvadvpn.util.JobTracker import net.mullvad.talpid.util.EventNotifier diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt index 9b41877f4c..447c215e1c 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt @@ -4,6 +4,7 @@ import java.net.InetAddress import java.util.ArrayList import kotlin.properties.Delegates.observable import net.mullvad.mullvadvpn.model.DnsOptions +import net.mullvad.mullvadvpn.service.endpoint.SettingsListener import net.mullvad.talpid.util.EventNotifier class CustomDns(val daemon: MullvadDaemon, val settingsListener: SettingsListener) { @@ -21,9 +22,11 @@ class CustomDns(val daemon: MullvadDaemon, val settingsListener: SettingsListene val onDnsServersChanged = EventNotifier<List<InetAddress>>(emptyList()) init { - settingsListener.dnsOptionsNotifier.subscribe(this) { dnsOptions -> - enabled = dnsOptions.custom - dnsServers = ArrayList(dnsOptions.addresses) + settingsListener.dnsOptionsNotifier.subscribe(this) { maybeDnsOptions -> + maybeDnsOptions?.let { dnsOptions -> + enabled = dnsOptions.custom + dnsServers = dnsOptions.addresses + } } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt index 0e43e7aa64..46719f9806 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt @@ -78,10 +78,9 @@ class MullvadVpnService : TalpidVpnService() { private var pendingAction by observable<PendingAction?>(null) { _, _, _ -> instance?.let { activeInstance -> - handlePendingAction( - activeInstance.connectionProxy, - activeInstance.settingsListener.settings - ) + endpoint.settingsListener.settings?.let { currentSettings -> + handlePendingAction(activeInstance.connectionProxy, currentSettings) + } } } @@ -232,9 +231,8 @@ class MullvadVpnService : TalpidVpnService() { } private suspend fun setUpInstance(daemon: MullvadDaemon, settings: Settings) { - val settingsListener = SettingsListener(daemon, settings) val connectionProxy = ConnectionProxy(this, daemon) - val customDns = CustomDns(daemon, settingsListener) + val customDns = CustomDns(daemon, endpoint.settingsListener) val splitTunneling = splitTunneling.await() splitTunneling.onChange = { excludedApps -> @@ -252,7 +250,7 @@ class MullvadVpnService : TalpidVpnService() { connectionProxy, connectivityListener, customDns, - settingsListener, + endpoint.settingsListener, splitTunneling ) } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt index 19d4443162..a124acfa64 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt @@ -1,6 +1,7 @@ package net.mullvad.mullvadvpn.service import android.os.Messenger +import net.mullvad.mullvadvpn.service.endpoint.SettingsListener import net.mullvad.talpid.ConnectivityListener class ServiceInstance( @@ -22,6 +23,5 @@ class ServiceInstance( customDns.onDestroy() keyStatusListener.onDestroy() locationInfoCache.onDestroy() - settingsListener.onDestroy() } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt deleted file mode 100644 index 5ffe9a1a2f..0000000000 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SettingsListener.kt +++ /dev/null @@ -1,65 +0,0 @@ -package net.mullvad.mullvadvpn.service - -import net.mullvad.mullvadvpn.model.RelaySettings -import net.mullvad.mullvadvpn.model.Settings -import net.mullvad.talpid.util.EventNotifier - -class SettingsListener(val daemon: MullvadDaemon, val initialSettings: Settings) { - var settings: Settings = initialSettings - private set(value) { - settingsNotifier.notify(value) - field = value - } - - private val settingsNotifier: EventNotifier<Settings> = EventNotifier(settings) - - val accountNumberNotifier = EventNotifier(initialSettings.accountToken) - val dnsOptionsNotifier = EventNotifier(initialSettings.tunnelOptions.dnsOptions) - - var onRelaySettingsChange: ((RelaySettings?) -> Unit)? = null - set(value) { - synchronized(this) { - field = value - value?.invoke(settings.relaySettings) - } - } - - init { - daemon.onSettingsChange.subscribe(this) { maybeSettings -> - maybeSettings?.let { settings -> handleNewSettings(settings) } - } - } - - fun onDestroy() { - daemon.onSettingsChange.unsubscribe(this) - - accountNumberNotifier.unsubscribeAll() - settingsNotifier.unsubscribeAll() - } - - fun subscribe(id: Any, listener: (Settings) -> Unit) { - settingsNotifier.subscribe(id, listener) - } - - fun unsubscribe(id: Any) { - settingsNotifier.unsubscribe(id) - } - - private fun handleNewSettings(newSettings: Settings) { - synchronized(this) { - if (settings.accountToken != newSettings.accountToken) { - accountNumberNotifier.notify(newSettings.accountToken) - } - - if (settings.tunnelOptions.dnsOptions != newSettings.tunnelOptions.dnsOptions) { - dnsOptionsNotifier.notify(newSettings.tunnelOptions.dnsOptions) - } - - if (settings.relaySettings != newSettings.relaySettings) { - onRelaySettingsChange?.invoke(newSettings.relaySettings) - } - - settings = newSettings - } - } -} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt index 6541ef2ba7..b9258c50ac 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt @@ -16,7 +16,10 @@ import net.mullvad.mullvadvpn.ipc.Request import net.mullvad.mullvadvpn.service.MullvadDaemon import net.mullvad.mullvadvpn.util.Intermittent -class ServiceEndpoint(looper: Looper, private val intermittentDaemon: Intermittent<MullvadDaemon>) { +class ServiceEndpoint( + looper: Looper, + internal val intermittentDaemon: Intermittent<MullvadDaemon> +) { private val listeners = mutableSetOf<Messenger>() private val registrationQueue: SendChannel<Messenger> = startRegistrator() @@ -26,6 +29,8 @@ class ServiceEndpoint(looper: Looper, private val intermittentDaemon: Intermitte val messenger = Messenger(dispatcher) + val settingsListener = SettingsListener(this) + init { dispatcher.registerHandler(Request.RegisterListener::class) { request -> registrationQueue.sendBlocking(request.listener) @@ -35,6 +40,8 @@ class ServiceEndpoint(looper: Looper, private val intermittentDaemon: Intermitte fun onDestroy() { dispatcher.onDestroy() registrationQueue.close() + + settingsListener.onDestroy() } internal fun sendEvent(event: Event) { @@ -74,7 +81,10 @@ class ServiceEndpoint(looper: Looper, private val intermittentDaemon: Intermitte synchronized(this) { listeners.add(listener) - val initialEvents = listOf(Event.ListenerReady) + val initialEvents = listOf( + Event.SettingsUpdate(settingsListener.settings), + Event.ListenerReady + ) initialEvents.forEach { event -> listener.send(event.message) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt new file mode 100644 index 0000000000..e1efe2f8c7 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/SettingsListener.kt @@ -0,0 +1,84 @@ +package net.mullvad.mullvadvpn.service.endpoint + +import net.mullvad.mullvadvpn.ipc.Event +import net.mullvad.mullvadvpn.model.DnsOptions +import net.mullvad.mullvadvpn.model.RelaySettings +import net.mullvad.mullvadvpn.model.Settings +import net.mullvad.mullvadvpn.service.MullvadDaemon +import net.mullvad.talpid.util.EventNotifier + +class SettingsListener(endpoint: ServiceEndpoint) { + private val daemon = endpoint.intermittentDaemon + + val accountNumberNotifier = EventNotifier<String?>(null) + val dnsOptionsNotifier = EventNotifier<DnsOptions?>(null) + val relaySettingsNotifier = EventNotifier<RelaySettings?>(null) + val settingsNotifier = EventNotifier<Settings?>(null) + + var settings by settingsNotifier.notifiable() + private set + + init { + daemon.registerListener(this) { newDaemon -> + if (newDaemon != null) { + registerListener(newDaemon) + fetchInitialSettings(newDaemon) + } + } + + settingsNotifier.subscribe(this) { settings -> + endpoint.sendEvent(Event.SettingsUpdate(settings)) + } + } + + fun onDestroy() { + daemon.unregisterListener(this) + + accountNumberNotifier.unsubscribeAll() + dnsOptionsNotifier.unsubscribeAll() + relaySettingsNotifier.unsubscribeAll() + settingsNotifier.unsubscribeAll() + } + + fun subscribe(id: Any, listener: (Settings) -> Unit) { + settingsNotifier.subscribe(id) { maybeSettings -> + maybeSettings?.let { settings -> + listener(settings) + } + } + } + + fun unsubscribe(id: Any) { + settingsNotifier.unsubscribe(id) + } + + private fun registerListener(daemon: MullvadDaemon) { + daemon.onSettingsChange.subscribe(this, ::handleNewSettings) + } + + private fun fetchInitialSettings(daemon: MullvadDaemon) { + synchronized(this) { + handleNewSettings(daemon.getSettings()) + } + } + + private fun handleNewSettings(newSettings: Settings?) { + if (newSettings != null) { + synchronized(this) { + if (settings?.accountToken != newSettings.accountToken) { + accountNumberNotifier.notify(newSettings.accountToken) + } + + if (settings?.tunnelOptions?.dnsOptions != newSettings.tunnelOptions.dnsOptions) { + dnsOptionsNotifier.notify(newSettings.tunnelOptions.dnsOptions) + } + + if (settings?.relaySettings != newSettings.relaySettings) { + relaySettingsNotifier.notify(newSettings.relaySettings) + } + + settings = newSettings + } + } + } +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt index 671a232220..97e82aa8ca 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt @@ -18,6 +18,8 @@ import net.mullvad.mullvadvpn.ui.widget.ToggleCell import net.mullvad.mullvadvpn.util.AdapterWithHeader class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) { + private var isAllowLanEnabled = false + private lateinit var customDnsAdapter: CustomDnsAdapter private lateinit var customDnsToggle: ToggleCell private lateinit var wireguardMtuInput: MtuCell @@ -67,7 +69,7 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) { detachBackButtonHandler() customDnsAdapter.onDestroy() titleController.onDestroy() - settingsListener.unsubscribe(this) + settingsListener.settingsNotifier.unsubscribe(this) } private fun configureHeader(view: View) { @@ -109,8 +111,12 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) { } } - settingsListener.subscribe(this) { settings -> - updateUi(settings) + settingsListener.settingsNotifier.subscribe(this) { maybeSettings -> + maybeSettings?.let { settings -> + updateUi(settings) + } + + isAllowLanEnabled = maybeSettings?.allowLan ?: false } } @@ -125,8 +131,7 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) { private suspend fun confirmAddAddress(address: InetAddress): Boolean { return when { address.isLinkLocalAddress() || address.isSiteLocalAddress() -> { - settingsListener.settings.allowLan || - showConfirmDnsServerDialog(R.string.confirm_local_dns) + isAllowLanEnabled || showConfirmDnsServerDialog(R.string.confirm_local_dns) } else -> showConfirmDnsServerDialog(R.string.confirm_public_dns) } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LaunchFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LaunchFragment.kt index 8e665dad01..c6ce330128 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LaunchFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LaunchFragment.kt @@ -12,7 +12,9 @@ class LaunchFragment : ServiceAwareFragment() { private val hasAccountToken = CompletableDeferred<Boolean>() override fun onNewServiceConnection(serviceConnection: ServiceConnection) { - hasAccountToken.complete(serviceConnection.settingsListener.settings.accountToken != null) + serviceConnection.settingsListener.accountNumberNotifier.subscribe(this) { accountToken -> + hasAccountToken.complete(accountToken != null) + } } override fun onCreateView( diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/PreferencesFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/PreferencesFragment.kt index d090017501..5452bf49c3 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/PreferencesFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/PreferencesFragment.kt @@ -26,8 +26,6 @@ class PreferencesFragment : ServiceDependentFragment(OnNoService.GoBack) { } allowLanToggle = view.findViewById<ToggleCell>(R.id.allow_lan).apply { - forcefullySetState(boolToSwitchState(settingsListener.settings.allowLan)) - listener = { state -> when (state) { CellSwitch.State.ON -> daemon.setAllowLan(true) @@ -37,8 +35,6 @@ class PreferencesFragment : ServiceDependentFragment(OnNoService.GoBack) { } autoConnectToggle = view.findViewById<ToggleCell>(R.id.auto_connect).apply { - forcefullySetState(boolToSwitchState(settingsListener.settings.autoConnect)) - listener = { state -> when (state) { CellSwitch.State.ON -> daemon.setAutoConnect(true) @@ -47,8 +43,10 @@ class PreferencesFragment : ServiceDependentFragment(OnNoService.GoBack) { } } - settingsListener.subscribe(this) { settings -> - updateUi(settings) + settingsListener.settingsNotifier.subscribe(this) { maybeSettings -> + maybeSettings?.let { settings -> + updateUi(settings) + } } titleController = CollapsibleTitleController(view) @@ -56,16 +54,24 @@ class PreferencesFragment : ServiceDependentFragment(OnNoService.GoBack) { return view } + override fun onSafelyDestroyView() { + titleController.onDestroy() + settingsListener.settingsNotifier.unsubscribe(this) + } + private fun updateUi(settings: Settings) { jobTracker.newUiJob("updateUi") { - allowLanToggle.state = boolToSwitchState(settings.allowLan) - autoConnectToggle.state = boolToSwitchState(settings.autoConnect) - } - } + val allowLanState = boolToSwitchState(settings.allowLan) + val autoConnectState = boolToSwitchState(settings.autoConnect) - override fun onSafelyDestroyView() { - titleController.onDestroy() - settingsListener.unsubscribe(this) + if (isVisible) { + allowLanToggle.state = allowLanState + autoConnectToggle.state = autoConnectState + } else { + allowLanToggle.forcefullySetState(allowLanState) + autoConnectToggle.forcefullySetState(autoConnectState) + } + } } private fun boolToSwitchState(pref: Boolean): CellSwitch.State { diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt index 30c0a6db30..6ff8b8c488 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt @@ -13,9 +13,9 @@ import net.mullvad.mullvadvpn.service.CustomDns import net.mullvad.mullvadvpn.service.KeyStatusListener import net.mullvad.mullvadvpn.service.LocationInfoCache import net.mullvad.mullvadvpn.service.MullvadDaemon -import net.mullvad.mullvadvpn.service.SettingsListener import net.mullvad.mullvadvpn.service.SplitTunneling import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnection +import net.mullvad.mullvadvpn.ui.serviceconnection.SettingsListener abstract class ServiceDependentFragment(val onNoService: OnNoService) : ServiceAwareFragment() { enum class OnNoService { diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt index d9071ca2b9..9bc22dd069 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt @@ -27,7 +27,7 @@ class ServiceConnection(private val service: ServiceInstance, val mainActivity: val customDns = service.customDns val keyStatusListener = service.keyStatusListener val locationInfoCache = service.locationInfoCache - val settingsListener = service.settingsListener + val settingsListener = SettingsListener(dispatcher) val splitTunneling = service.splitTunneling val appVersionInfoCache = AppVersionInfoCache(mainActivity, daemon, settingsListener) @@ -42,6 +42,8 @@ class ServiceConnection(private val service: ServiceInstance, val mainActivity: fun onDestroy() { dispatcher.onDestroy() + settingsListener.onDestroy() + appVersionInfoCache.onDestroy() relayListListener.onDestroy() connectionProxy.mainActivity = null diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt new file mode 100644 index 0000000000..f98b8a27ae --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/SettingsListener.kt @@ -0,0 +1,48 @@ +package net.mullvad.mullvadvpn.ui.serviceconnection + +import net.mullvad.mullvadvpn.ipc.DispatchingHandler +import net.mullvad.mullvadvpn.ipc.Event +import net.mullvad.mullvadvpn.model.DnsOptions +import net.mullvad.mullvadvpn.model.RelaySettings +import net.mullvad.mullvadvpn.model.Settings +import net.mullvad.talpid.util.EventNotifier + +class SettingsListener(eventDispatcher: DispatchingHandler<Event>) { + val accountNumberNotifier = EventNotifier<String?>(null) + val dnsOptionsNotifier = EventNotifier<DnsOptions?>(null) + val relaySettingsNotifier = EventNotifier<RelaySettings?>(null) + val settingsNotifier = EventNotifier<Settings?>(null) + + private var settings by settingsNotifier.notifiable() + + init { + eventDispatcher.registerHandler(Event.SettingsUpdate::class, ::handleNewEvent) + } + + fun onDestroy() { + accountNumberNotifier.unsubscribeAll() + dnsOptionsNotifier.unsubscribeAll() + relaySettingsNotifier.unsubscribeAll() + settingsNotifier.unsubscribeAll() + } + + private fun handleNewEvent(event: Event.SettingsUpdate) { + event.settings?.let { settings -> handleNewSettings(settings) } + } + + private fun handleNewSettings(newSettings: Settings) { + if (settings?.accountToken != newSettings.accountToken) { + accountNumberNotifier.notify(newSettings.accountToken) + } + + if (settings?.tunnelOptions?.dnsOptions != newSettings.tunnelOptions.dnsOptions) { + dnsOptionsNotifier.notify(newSettings.tunnelOptions.dnsOptions) + } + + if (settings?.relaySettings != newSettings.relaySettings) { + relaySettingsNotifier.notify(newSettings.relaySettings) + } + + settings = newSettings + } +} diff --git a/android/src/main/kotlin/net/mullvad/talpid/net/wireguard/TunnelOptions.kt b/android/src/main/kotlin/net/mullvad/talpid/net/wireguard/TunnelOptions.kt index bbba95fa6d..f5c5811c67 100644 --- a/android/src/main/kotlin/net/mullvad/talpid/net/wireguard/TunnelOptions.kt +++ b/android/src/main/kotlin/net/mullvad/talpid/net/wireguard/TunnelOptions.kt @@ -1,3 +1,7 @@ package net.mullvad.talpid.net.wireguard -data class TunnelOptions(val mtu: Int?) +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class TunnelOptions(val mtu: Int?) : Parcelable diff --git a/mullvad-types/src/relay_constraints.rs b/mullvad-types/src/relay_constraints.rs index d1104f4733..908b0d3215 100644 --- a/mullvad-types/src/relay_constraints.rs +++ b/mullvad-types/src/relay_constraints.rs @@ -22,6 +22,7 @@ pub trait Match<T> { #[serde(rename_all = "snake_case")] #[cfg_attr(target_os = "android", derive(FromJava, IntoJava))] #[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] +#[cfg_attr(target_os = "android", jnix(bounds = "T: android.os.Parcelable"))] pub enum Constraint<T: fmt::Debug + Clone + Eq + PartialEq> { Any, Only(T), |
