summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-06-25 08:21:21 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-06-25 08:21:21 -0300
commit58590ea31af530bca88b155d33aedc5d53a8b9c7 (patch)
tree9f8b0591becacfaf1c6f62aef49385699d96ce07
parent48348ce6f9a599ec0f59ba784171be7bae32078f (diff)
parent41fad40024e7741c57e8a25cd576c61ae7bbd31b (diff)
downloadmullvadvpn-58590ea31af530bca88b155d33aedc5d53a8b9c7.tar.xz
mullvadvpn-58590ea31af530bca88b155d33aedc5d53a8b9c7.zip
Merge branch 'fix-country-not-selected'
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/AccountFragment.kt38
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt3
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt3
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt33
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt5
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt10
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/RemainingTimeLabel.kt23
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/SelectLocationFragment.kt11
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/SettingsFragment.kt6
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AccountCache.kt76
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt43
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/SettingsListener.kt72
-rw-r--r--mullvad-jni/src/jni_event_listener.rs30
14 files changed, 244 insertions, 115 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/AccountFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/AccountFragment.kt
index 8bcd8506a7..88093337d3 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/AccountFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/AccountFragment.kt
@@ -58,25 +58,37 @@ class AccountFragment : Fragment() {
accountNumberContainer.setOnClickListener { copyAccountNumberToClipboard() }
- updateViewJob = updateView()
-
return view
}
- private fun updateView() = GlobalScope.launch(Dispatchers.Main) {
- val accountCache = parentActivity.accountCache
- val accountNumber = accountCache.accountNumber.await()
+ override fun onResume() {
+ super.onResume()
+
+ parentActivity.accountCache.onAccountDataChange = { accountNumber, accountExpiry ->
+ updateViewJob = updateView(accountNumber, accountExpiry)
+ }
+ }
+
+ override fun onPause() {
+ parentActivity.accountCache.onAccountDataChange = null
+ super.onPause()
+ }
+
+ private fun updateView(accountNumber: String?, accountExpiry: DateTime?) =
+ GlobalScope.launch(Dispatchers.Main) {
if (accountNumber != null) {
- accountNumberDisplay.setText(accountCache.accountNumber.await())
+ accountNumberDisplay.setText(accountNumber)
accountNumberContainer.visibility = View.VISIBLE
+ } else {
+ accountNumberContainer.visibility = View.INVISIBLE
+ }
- val accountExpiry = accountCache.accountExpiry.await()
-
- if (accountExpiry != null) {
- accountExpiryDisplay.setText(formatExpiry(accountExpiry))
- accountExpiryContainer.visibility = View.VISIBLE
- }
+ if (accountExpiry != null) {
+ accountExpiryDisplay.setText(formatExpiry(accountExpiry))
+ accountExpiryContainer.visibility = View.VISIBLE
+ } else {
+ accountExpiryContainer.visibility = View.INVISIBLE
}
}
@@ -106,7 +118,7 @@ class AccountFragment : Fragment() {
}
private fun clearAccountNumber() = GlobalScope.launch(Dispatchers.Default) {
- val daemon = parentActivity.asyncDaemon.await()
+ val daemon = parentActivity.daemon.await()
daemon.setAccount(null)
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
index f627ad789a..c31b1691dc 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
@@ -54,7 +54,7 @@ class ConnectFragment : Fragment() {
parentActivity = context as MainActivity
locationInfoCache = parentActivity.locationInfoCache
relayListListener = parentActivity.relayListListener
- waitForDaemonJob = waitForDaemon(parentActivity.asyncDaemon)
+ waitForDaemonJob = waitForDaemon(parentActivity.daemon)
}
override fun onCreateView(
@@ -123,9 +123,9 @@ class ConnectFragment : Fragment() {
}
}
- private fun waitForDaemon(asyncDaemon: Deferred<MullvadDaemon>) =
+ private fun waitForDaemon(originalDaemon: Deferred<MullvadDaemon>) =
GlobalScope.launch(Dispatchers.Default) {
- daemon.complete(asyncDaemon.await())
+ daemon.complete(originalDaemon.await())
}
private fun attachListener() = GlobalScope.launch(Dispatchers.Default) {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt
index f2a5a5a97f..7b2ebc4453 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/LaunchFragment.kt
@@ -38,7 +38,8 @@ class LaunchFragment : Fragment() {
private fun checkForAccountToken() = GlobalScope.async(Dispatchers.Default) {
val parentActivity = activity as MainActivity
- val settings = parentActivity.asyncSettings.await()
+ val daemon = parentActivity.daemon.await()
+ val settings = daemon.getSettings()
settings.accountToken != null
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt
index 80b000d643..e8b42d038c 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt
@@ -70,7 +70,7 @@ class LoginFragment : Fragment() {
private fun performLogin(accountToken: String) = GlobalScope.launch(Dispatchers.Main) {
loginJob?.cancel()
loginJob = GlobalScope.async(Dispatchers.Default) {
- val daemon = parentActivity.asyncDaemon.await()
+ val daemon = parentActivity.daemon.await()
val accountData = daemon.getAccountData(accountToken)
if (accountData != null) {
@@ -90,7 +90,6 @@ class LoginFragment : Fragment() {
private suspend fun loggedIn() {
showLoggedInMessage()
- parentActivity.refetchSettings()
delay(1000)
openConnectScreen()
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt
index 1731ce2a56..457cefa3dc 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt
@@ -20,25 +20,21 @@ import net.mullvad.mullvadvpn.dataproxy.AccountCache
import net.mullvad.mullvadvpn.dataproxy.LocationInfoCache
import net.mullvad.mullvadvpn.dataproxy.MullvadProblemReport
import net.mullvad.mullvadvpn.dataproxy.RelayListListener
+import net.mullvad.mullvadvpn.dataproxy.SettingsListener
import net.mullvad.mullvadvpn.model.RelaySettings
import net.mullvad.mullvadvpn.model.Settings
import net.mullvad.mullvadvpn.relaylist.RelayItem
import net.mullvad.mullvadvpn.relaylist.RelayList
class MainActivity : FragmentActivity() {
- var asyncDaemon = CompletableDeferred<MullvadDaemon>()
- val daemon
- get() = runBlocking { asyncDaemon.await() }
-
- var asyncSettings = fetchSettings()
+ var daemon = CompletableDeferred<MullvadDaemon>()
private set
- val settings
- get() = runBlocking { asyncSettings.await() }
- val accountCache = AccountCache(this)
- val locationInfoCache = LocationInfoCache(asyncDaemon)
+ val locationInfoCache = LocationInfoCache(daemon)
val problemReport = MullvadProblemReport()
+ var settingsListener = SettingsListener(this)
var relayListListener = RelayListListener(this)
+ val accountCache = AccountCache(settingsListener, daemon)
private var waitForDaemonJob: Job? = null
@@ -47,13 +43,13 @@ class MainActivity : FragmentActivity() {
val localBinder = binder as MullvadVpnService.LocalBinder
waitForDaemonJob = GlobalScope.launch(Dispatchers.Default) {
- asyncDaemon.complete(localBinder.asyncDaemon.await())
+ daemon.complete(localBinder.daemon.await())
}
}
override fun onServiceDisconnected(className: ComponentName) {
- asyncDaemon.cancel()
- asyncDaemon = CompletableDeferred<MullvadDaemon>()
+ daemon.cancel()
+ daemon = CompletableDeferred<MullvadDaemon>()
}
}
@@ -84,10 +80,10 @@ class MainActivity : FragmentActivity() {
override fun onDestroy() {
accountCache.onDestroy()
relayListListener.onDestroy()
+ settingsListener.onDestroy()
waitForDaemonJob?.cancel()
- asyncSettings.cancel()
- asyncDaemon.cancel()
+ daemon.cancel()
super.onDestroy()
}
@@ -106,13 +102,6 @@ class MainActivity : FragmentActivity() {
}
}
- fun refetchSettings() {
- if (asyncSettings.isCompleted) {
- asyncSettings = fetchSettings()
- accountCache.settings = asyncSettings
- }
- }
-
private fun addInitialFragment() {
supportFragmentManager?.beginTransaction()?.apply {
add(R.id.main_fragment, LaunchFragment())
@@ -121,6 +110,6 @@ class MainActivity : FragmentActivity() {
}
private fun fetchSettings() = GlobalScope.async(Dispatchers.Default) {
- asyncDaemon.await().getSettings()
+ daemon.await().getSettings()
}
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
index a777611c84..7033f13de7 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
@@ -15,6 +15,7 @@ class MullvadDaemon(val vpnService: MullvadVpnService) {
}
var onRelayListChange: ((RelayList) -> Unit)? = null
+ var onSettingsChange: ((Settings) -> Unit)? = null
var onTunnelStateChange: ((TunnelStateTransition) -> Unit)? = null
external fun connect()
@@ -35,6 +36,10 @@ class MullvadDaemon(val vpnService: MullvadVpnService) {
onRelayListChange?.invoke(relayList)
}
+ private fun notifySettingsEvent(settings: Settings) {
+ onSettingsChange?.invoke(settings)
+ }
+
private fun notifyTunnelStateEvent(event: TunnelStateTransition) {
onTunnelStateChange?.invoke(event)
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
index e728752461..d8c340bcd2 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
@@ -22,9 +22,7 @@ class MullvadVpnService : VpnService() {
private val created = CompletableDeferred<Unit>()
private val binder = LocalBinder()
- val asyncDaemon = startDaemon()
- val daemon
- get() = runBlocking { asyncDaemon.await() }
+ val daemon = startDaemon()
override fun onCreate() {
created.complete(Unit)
@@ -37,7 +35,7 @@ class MullvadVpnService : VpnService() {
override fun onDestroy() {
connectivityListener.unregister(this)
- asyncDaemon.cancel()
+ daemon.cancel()
created.cancel()
}
@@ -72,8 +70,8 @@ class MullvadVpnService : VpnService() {
}
inner class LocalBinder : Binder() {
- val asyncDaemon
- get() = this@MullvadVpnService.asyncDaemon
+ val daemon
+ get() = this@MullvadVpnService.daemon
}
private fun startDaemon() = GlobalScope.async(Dispatchers.Default) {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/RemainingTimeLabel.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/RemainingTimeLabel.kt
index 6e772c1675..f0335d3914 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/RemainingTimeLabel.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/RemainingTimeLabel.kt
@@ -1,9 +1,9 @@
package net.mullvad.mullvadvpn
-import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.Job
import org.joda.time.format.DateTimeFormat
import org.joda.time.DateTime
@@ -23,22 +23,25 @@ class RemainingTimeLabel(val parentActivity: MainActivity, val view: View) {
private val label = view.findViewById<TextView>(R.id.remaining_time)
- private var updateJob = updateLabel()
+ private var updateJob: Job? = null
fun onResume() {
- if (updateJob.isCompleted) {
- parentActivity.refetchSettings()
- updateJob = updateLabel()
+ parentActivity.accountCache.apply {
+ refetch()
+
+ onAccountDataChange = { accountNumber, accountExpiry ->
+ updateJob?.cancel()
+ updateJob = updateLabel(accountExpiry)
+ }
}
}
- fun onDestroy() {
- updateJob.cancel()
+ fun onPause() {
+ parentActivity.accountCache.onAccountDataChange = null
+ updateJob?.cancel()
}
- private fun updateLabel() = GlobalScope.launch(Dispatchers.Main) {
- val expiry = accountCache.accountExpiry.await()
-
+ private fun updateLabel(expiry: DateTime?) = GlobalScope.launch(Dispatchers.Main) {
if (expiry != null) {
val remainingTime = Duration(DateTime.now(), expiry)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/SelectLocationFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/SelectLocationFragment.kt
index 96519c1893..f0d9af7913 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/SelectLocationFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/SelectLocationFragment.kt
@@ -37,8 +37,7 @@ class SelectLocationFragment : Fragment() {
init {
relayListAdapter.onSelect = { relayItem ->
- relayListListener.selectedRelayItem = relayItem
- updateLocationConstraint()
+ updateLocationConstraint(relayItem)
close()
}
}
@@ -100,10 +99,12 @@ class SelectLocationFragment : Fragment() {
}
}
- private fun updateLocationConstraint() = GlobalScope.launch(Dispatchers.Default) {
- val constraint = relayListListener.selectedRelayLocation
+ private fun updateLocationConstraint(relayItem: RelayItem?) =
+ GlobalScope.launch(Dispatchers.Default) {
+ val constraint: Constraint<LocationConstraint> =
+ relayItem?.run { Constraint.Only(location) } ?: Constraint.Any()
- parentActivity.asyncDaemon.await().updateRelaySettings(
+ parentActivity.daemon.await().updateRelaySettings(
RelaySettingsUpdate.RelayConstraintsUpdate(constraint)
)
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/SettingsFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/SettingsFragment.kt
index 3400d43e58..f82ef1e0a9 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/SettingsFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/SettingsFragment.kt
@@ -51,9 +51,9 @@ class SettingsFragment : Fragment() {
remainingTimeLabel.onResume()
}
- override fun onDestroyView() {
- remainingTimeLabel.onDestroy()
- super.onDestroyView()
+ override fun onPause() {
+ remainingTimeLabel.onPause()
+ super.onPause()
}
private fun openSubFragment(fragment: Fragment) {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AccountCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AccountCache.kt
index 41d23b4a26..f47ffd5bb6 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AccountCache.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/AccountCache.kt
@@ -1,54 +1,76 @@
package net.mullvad.mullvadvpn.dataproxy
-import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.Job
import org.joda.time.format.DateTimeFormat
import org.joda.time.DateTime
-import net.mullvad.mullvadvpn.MainActivity
+import net.mullvad.mullvadvpn.MullvadDaemon
val EXPIRY_FORMAT = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss z")
-class AccountCache(val parentActivity: MainActivity) {
- private var daemon = parentActivity.asyncDaemon
+class AccountCache(val settingsListener: SettingsListener, val daemon: Deferred<MullvadDaemon>) {
+ private var fetchJob: Job? = null
+ private var accountNumber: String? = null
+ private var accountExpiry: DateTime? = null
- var settings = parentActivity.asyncSettings
+ var onAccountDataChange: ((String?, DateTime?) -> Unit)? = null
set(value) {
- field = value
- accountNumber = fetchAccountNumber()
- accountExpiry = fetchAccountExpiry()
+ synchronized(this) {
+ field = value
+ notifyChange()
+ }
+ }
+
+ init {
+ settingsListener.onAccountNumberChange = { accountNumber ->
+ handleNewAccountNumber(accountNumber)
}
+ }
- var accountNumber = fetchAccountNumber()
- private set
- var accountExpiry = fetchAccountExpiry()
- private set
+ fun refetch() {
+ fetchJob?.cancel()
+ fetchJob = fetchAccountExpiry()
+ }
fun onDestroy() {
- accountExpiry.cancel()
- accountNumber.cancel()
+ settingsListener.onAccountNumberChange = null
+
+ fetchJob?.cancel()
}
- private fun fetchAccountNumber() = GlobalScope.async(Dispatchers.Default) {
- settings.await().accountToken
+ private fun handleNewAccountNumber(newAccountNumber: String?) {
+ synchronized(this) {
+ accountNumber = newAccountNumber
+ accountExpiry = null
+
+ notifyChange()
+ refetch()
+ }
}
- private fun fetchAccountExpiry() = GlobalScope.async(Dispatchers.Default) {
- val accountNumber = accountNumber.await()
+ private fun fetchAccountExpiry() = GlobalScope.launch(Dispatchers.Default) {
+ val accountNumber = this@AccountCache.accountNumber
+ val accountData = accountNumber?.let { account ->
+ daemon.await().getAccountData(account)
+ }
- if (accountNumber != null) {
- val accountData = daemon.await().getAccountData(accountNumber)
- val accountExpiry = accountData?.expiry
+ synchronized(this@AccountCache) {
+ if (this@AccountCache.accountNumber === accountNumber) {
+ accountExpiry = accountData?.expiry?.let { expiry ->
+ DateTime.parse(expiry, EXPIRY_FORMAT)
+ }
- if (accountExpiry != null) {
- DateTime.parse(accountExpiry, EXPIRY_FORMAT)
- } else {
- null
+ notifyChange()
}
- } else {
- null
}
}
+
+ private fun notifyChange() {
+ onAccountDataChange?.invoke(accountNumber, accountExpiry)
+ }
}
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 64121aac96..d1a33b2f38 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt
@@ -21,21 +21,7 @@ class RelayListListener(val parentActivity: MainActivity) {
private var relaySettings: RelaySettings? = null
var selectedRelayItem: RelayItem? = null
- set(value) {
- field = value
- updateRelaySettings()
- }
-
- val selectedRelayLocation: Constraint<LocationConstraint>
- get() {
- val location = selectedRelayItem?.location
-
- if (location == null) {
- return Constraint.Any()
- } else {
- return Constraint.Only(location)
- }
- }
+ private set
var onRelayListChange: ((RelayList, RelayItem?) -> Unit)? = null
set(value) {
@@ -50,8 +36,15 @@ class RelayListListener(val parentActivity: MainActivity) {
}
}
+ init {
+ parentActivity.settingsListener.onRelaySettingsChange = { newRelaySettings ->
+ relaySettingsChanged(newRelaySettings)
+ }
+ }
+
fun onDestroy() {
setUpJob.cancel()
+ parentActivity.settingsListener.onRelaySettingsChange = null
if (daemon.isActive) {
daemon.cancel()
@@ -61,7 +54,7 @@ class RelayListListener(val parentActivity: MainActivity) {
}
private fun setUp() = GlobalScope.launch(Dispatchers.Default) {
- daemon.complete(parentActivity.asyncDaemon.await())
+ daemon.complete(parentActivity.daemon.await())
setUpListener()
fetchInitialRelayList()
@@ -76,8 +69,6 @@ class RelayListListener(val parentActivity: MainActivity) {
private suspend fun fetchInitialRelayList() {
val relayLocations = daemon.await().getRelayLocations()
- relaySettings = parentActivity.asyncSettings.await().relaySettings
-
synchronized(this) {
if (relayList == null) {
relayListChanged(RelayList(relayLocations))
@@ -85,6 +76,18 @@ class RelayListListener(val parentActivity: MainActivity) {
}
}
+ private fun relaySettingsChanged(newRelaySettings: RelaySettings?) {
+ synchronized(this) {
+ val relayList = this.relayList
+
+ relaySettings = newRelaySettings ?: RelaySettings.RelayConstraints(Constraint.Any())
+
+ if (relayList != null) {
+ relayListChanged(relayList)
+ }
+ }
+ }
+
private fun relayListChanged(newRelayList: RelayList) {
synchronized(this) {
relayList = newRelayList
@@ -108,8 +111,4 @@ class RelayListListener(val parentActivity: MainActivity) {
return null
}
-
- private fun updateRelaySettings() {
- relaySettings = RelaySettings.RelayConstraints(selectedRelayLocation)
- }
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/SettingsListener.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/SettingsListener.kt
new file mode 100644
index 0000000000..63b589fbca
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/SettingsListener.kt
@@ -0,0 +1,72 @@
+package net.mullvad.mullvadvpn.dataproxy
+
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+
+import net.mullvad.mullvadvpn.MainActivity
+import net.mullvad.mullvadvpn.model.RelaySettings
+import net.mullvad.mullvadvpn.model.Settings
+import net.mullvad.mullvadvpn.MullvadDaemon
+
+class SettingsListener(val parentActivity: MainActivity) {
+ private lateinit var daemon: MullvadDaemon
+
+ private val setUpJob = setUp()
+
+ private var settings: Settings? = null
+
+ var onAccountNumberChange: ((String?) -> Unit)? = null
+ set(value) {
+ synchronized(this) {
+ field = value
+ value?.invoke(settings?.accountToken)
+ }
+ }
+
+ var onRelaySettingsChange: ((RelaySettings?) -> Unit)? = null
+ set(value) {
+ synchronized(this) {
+ field = value
+ value?.invoke(settings?.relaySettings)
+ }
+ }
+
+ fun onDestroy() {
+ setUpJob.cancel()
+
+ if (::daemon.isInitialized) {
+ daemon.onSettingsChange = null
+ }
+ }
+
+ private fun setUp() = GlobalScope.launch(Dispatchers.Default) {
+ daemon = parentActivity.daemon.await()
+ daemon.onSettingsChange = { settings -> handleNewSettings(settings) }
+ fetchInitialSettings()
+ }
+
+ private fun fetchInitialSettings() {
+ val initialSettings = daemon!!.getSettings()
+
+ synchronized(this) {
+ if (settings == null) {
+ handleNewSettings(initialSettings)
+ }
+ }
+ }
+
+ private fun handleNewSettings(newSettings: Settings) {
+ synchronized(this) {
+ if (settings?.accountToken != newSettings.accountToken) {
+ onAccountNumberChange?.invoke(newSettings.accountToken)
+ }
+
+ if (settings?.relaySettings != newSettings.relaySettings) {
+ onRelaySettingsChange?.invoke(newSettings.relaySettings)
+ }
+
+ settings = newSettings
+ }
+ }
+}
diff --git a/mullvad-jni/src/jni_event_listener.rs b/mullvad-jni/src/jni_event_listener.rs
index 3b82cc5b9b..9a89d85927 100644
--- a/mullvad-jni/src/jni_event_listener.rs
+++ b/mullvad-jni/src/jni_event_listener.rs
@@ -23,6 +23,7 @@ pub enum Error {
enum Event {
RelayList(RelayList),
+ Settings(Settings),
Tunnel(TunnelStateTransition),
}
@@ -40,7 +41,9 @@ impl EventListener for JniEventListener {
let _ = self.0.send(Event::Tunnel(state));
}
- fn notify_settings(&self, _: Settings) {}
+ fn notify_settings(&self, settings: Settings) {
+ let _ = self.0.send(Event::Settings(settings));
+ }
fn notify_relay_list(&self, relay_list: RelayList) {
let _ = self.0.send(Event::RelayList(relay_list));
@@ -51,6 +54,7 @@ struct JniEventHandler<'env> {
env: AttachGuard<'env>,
mullvad_ipc_client: JObject<'env>,
notify_relay_list_event: JMethodID<'env>,
+ notify_settings_event: JMethodID<'env>,
notify_tunnel_event: JMethodID<'env>,
events: mpsc::Receiver<Event>,
}
@@ -98,6 +102,12 @@ impl<'env> JniEventHandler<'env> {
"notifyRelayListEvent",
"(Lnet/mullvad/mullvadvpn/model/RelayList;)V",
)?;
+ let notify_settings_event = Self::get_method_id(
+ &env,
+ &class,
+ "notifySettingsEvent",
+ "(Lnet/mullvad/mullvadvpn/model/Settings;)V",
+ )?;
let notify_tunnel_event = Self::get_method_id(
&env,
&class,
@@ -109,6 +119,7 @@ impl<'env> JniEventHandler<'env> {
env,
mullvad_ipc_client,
notify_relay_list_event,
+ notify_settings_event,
notify_tunnel_event,
events,
})
@@ -128,6 +139,7 @@ impl<'env> JniEventHandler<'env> {
while let Ok(event) = self.events.recv() {
match event {
Event::RelayList(relay_list) => self.handle_relay_list_event(relay_list),
+ Event::Settings(settings) => self.handle_settings(settings),
Event::Tunnel(tunnel_event) => self.handle_tunnel_event(tunnel_event),
}
}
@@ -149,6 +161,22 @@ impl<'env> JniEventHandler<'env> {
}
}
+ fn handle_settings(&self, settings: Settings) {
+ let result = self.env.call_method_unchecked(
+ self.mullvad_ipc_client,
+ self.notify_settings_event,
+ JavaType::Primitive(Primitive::Void),
+ &[JValue::Object(settings.into_java(&self.env))],
+ );
+
+ if let Err(error) = result {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to call MullvadDaemon.notifySettingsEvent")
+ );
+ }
+ }
+
fn handle_tunnel_event(&self, event: TunnelStateTransition) {
let result = self.env.call_method_unchecked(
self.mullvad_ipc_client,