summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2021-11-30 10:05:41 +0100
committerAlbin <albin@mullvad.net>2021-12-07 16:09:36 +0100
commit77de6ab76c023d40dde8cf13a7831e454cd75944 (patch)
treed42a4acd86f65fadb3fb5a31618d80df83f72eb6 /android
parent2bb48d64f1fe377a4b02880648768df7ba532eba (diff)
downloadmullvadvpn-77de6ab76c023d40dde8cf13a7831e454cd75944.tar.xz
mullvadvpn-77de6ab76c023d40dde8cf13a7831e454cd75944.zip
Fix custom dns toggle not working after resume
Fixes an issue with the custom dns toggle and server list not not working after the app is resumed, due to the logic not being aware of new service connections. The issue was fixed by moving some responsibility from the adapter to the fragment and making sure new service connections triggers new data subscriptions to be set up.
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt97
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt59
2 files changed, 92 insertions, 64 deletions
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 6f1568327d..33fbd295ea 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt
@@ -11,6 +11,7 @@ import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.model.Settings
import net.mullvad.mullvadvpn.ui.customdns.CustomDnsAdapter
import net.mullvad.mullvadvpn.ui.fragments.SplitTunnelingFragment
+import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnection
import net.mullvad.mullvadvpn.ui.widget.CellSwitch
import net.mullvad.mullvadvpn.ui.widget.CustomRecyclerView
import net.mullvad.mullvadvpn.ui.widget.MtuCell
@@ -21,8 +22,11 @@ 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
+ // Both customDnsAdapter and customDnsToggle are nullable since onNewServiceConnection,
+ // which sets up custom dns subscriptions, is called before onSafelyCreateView.
+ private var customDnsAdapter: CustomDnsAdapter? = null
+ private var customDnsToggle: ToggleCell? = null
+
private lateinit var wireguardMtuInput: MtuCell
private lateinit var titleController: CollapsibleTitleController
@@ -34,31 +38,45 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
val view = inflater.inflate(R.layout.advanced, container, false)
view.findViewById<View>(R.id.back).setOnClickListener {
- customDnsAdapter.stopEditing()
+ customDnsAdapter?.stopEditing()
parentActivity.onBackPressed()
}
titleController = CollapsibleTitleController(view, R.id.contents)
- customDnsAdapter = CustomDnsAdapter(customDns).apply {
- confirmAddAddress = ::confirmAddAddress
- }
+ customDnsAdapter = CustomDnsAdapter(
+ onAddServer = { address -> customDns.addDnsServer(address) },
+ onRemoveDnsServer = { address -> customDns.removeDnsServer(address) },
+ onSetCustomDnsEnabled = { isEnabled ->
+ if (isEnabled) {
+ customDns.enable()
+ } else {
+ customDns.disable()
+ }
+ },
+ onReplaceDnsServer = { oldServer, newServer ->
+ customDns.replaceDnsServer(oldServer, newServer)
+ }
+ ).also { newCustomDnsAdapter ->
+ newCustomDnsAdapter.confirmAddAddress = ::confirmAddAddress
- view.findViewById<CustomRecyclerView>(R.id.contents).apply {
- layoutManager = LinearLayoutManager(parentActivity)
+ view.findViewById<CustomRecyclerView>(R.id.contents).apply {
+ layoutManager = LinearLayoutManager(parentActivity)
- adapter = AdapterWithHeader(customDnsAdapter, R.layout.advanced_header).apply {
- onHeaderAvailable = { headerView ->
- configureHeader(headerView)
- titleController.expandedTitleView = headerView.findViewById(R.id.expanded_title)
+ adapter = AdapterWithHeader(newCustomDnsAdapter, R.layout.advanced_header).apply {
+ onHeaderAvailable = { headerView ->
+ configureHeader(headerView)
+ titleController.expandedTitleView =
+ headerView.findViewById(R.id.expanded_title)
+ }
}
- }
- addItemDecoration(
- ListItemDividerDecoration(
- topOffset = resources.getDimensionPixelSize(R.dimen.list_item_divider)
+ addItemDecoration(
+ ListItemDividerDecoration(
+ topOffset = resources.getDimensionPixelSize(R.dimen.list_item_divider)
+ )
)
- )
+ }
}
attachBackButtonHandler()
@@ -66,9 +84,14 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
return view
}
+ override fun onNewServiceConnection(serviceConnection: ServiceConnection) {
+ super.onNewServiceConnection(serviceConnection)
+ subscribeToCustomDnsChanges()
+ }
+
override fun onSafelyDestroyView() {
detachBackButtonHandler()
- customDnsAdapter.onDestroy()
+ customDnsAdapter?.onDestroy()
titleController.onDestroy()
settingsListener.settingsNotifier.unsubscribe(this)
}
@@ -98,16 +121,6 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
}
}
- customDns.onEnabledChanged.subscribe(this) { enabled ->
- jobTracker.newUiJob("updateEnabled") {
- if (enabled) {
- customDnsToggle.state = CellSwitch.State.ON
- } else {
- customDnsToggle.state = CellSwitch.State.OFF
- }
- }
- }
-
settingsListener.settingsNotifier.subscribe(this) { maybeSettings ->
maybeSettings?.let { settings ->
updateUi(settings)
@@ -115,6 +128,30 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
isAllowLanEnabled = maybeSettings?.allowLan ?: false
}
+
+ subscribeToCustomDnsChanges()
+ }
+
+ private fun subscribeToCustomDnsChanges() {
+ // Ensure there are no previous subscriptions as this function might be called either when
+ // there view has been created or when there is a new service connection.
+ customDns.onEnabledChanged.unsubscribe(this)
+ customDns.onDnsServersChanged.unsubscribe(this)
+
+ customDns.onEnabledChanged.subscribe(this) { isEnabled ->
+ customDnsAdapter?.updateState(isEnabled)
+ jobTracker.newUiJob("updateEnabled") {
+ if (isEnabled) {
+ customDnsToggle?.state = CellSwitch.State.ON
+ } else {
+ customDnsToggle?.state = CellSwitch.State.OFF
+ }
+ }
+ }
+
+ customDns.onDnsServersChanged.subscribe(this) { servers ->
+ customDnsAdapter?.updateServers(servers)
+ }
}
private fun updateUi(settings: Settings) {
@@ -150,8 +187,8 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
private fun attachBackButtonHandler() {
parentActivity.backButtonHandler = {
- if (customDnsAdapter.isEditing) {
- customDnsAdapter.stopEditing()
+ if (customDnsAdapter?.isEditing == true) {
+ customDnsAdapter?.stopEditing()
}
false
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt
index 1c8b36e062..1ab1429b49 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt
@@ -8,11 +8,15 @@ import kotlin.properties.Delegates.observable
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.ui.serviceconnection.CustomDns
import net.mullvad.mullvadvpn.util.JobTracker
import org.apache.commons.validator.routines.InetAddressValidator
-class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>() {
+class CustomDnsAdapter(
+ val onSetCustomDnsEnabled: (Boolean) -> Unit,
+ val onAddServer: (InetAddress) -> Boolean,
+ val onRemoveDnsServer: (InetAddress) -> Unit,
+ val onReplaceDnsServer: (InetAddress, InetAddress) -> Boolean
+) : Adapter<CustomDnsItemHolder>() {
private enum class ViewTypes {
ADD_SERVER,
EDIT_SERVER,
@@ -40,10 +44,6 @@ class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>(
if (oldValue != newValue) {
if (newValue == true) {
notifyItemRangeInserted(0, cachedCustomDnsServers.size + 1)
-
- if (cachedCustomDnsServers.isEmpty()) {
- editingPosition = 0
- }
} else {
notifyItemRangeRemoved(0, cachedCustomDnsServers.size + 1)
editingPosition = null
@@ -57,28 +57,24 @@ class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>(
// By default, refuse the address so that the dialog can be recreated by the user if needed
var confirmAddAddress: suspend (InetAddress) -> Boolean = { false }
- init {
- customDns.apply {
- onDnsServersChanged.subscribe(this) { dnsServers ->
- jobTracker.newBackgroundJob("toggleCustomDns") {
- if (dnsServers.isEmpty()) {
- customDns.disable()
- }
- }
+ fun updateServers(servers: List<InetAddress>) {
+ jobTracker.newBackgroundJob("toggleCustomDns") {
+ if (servers.isEmpty()) {
+ onSetCustomDnsEnabled(false)
+ }
+ }
- jobTracker.newUiJob("updateDnsServers") {
- customDnsServersLock.withLock {
- activeCustomDnsServers = dnsServers
- }
- }
+ jobTracker.newUiJob("updateDnsServers") {
+ customDnsServersLock.withLock {
+ activeCustomDnsServers = servers
}
+ }
+ }
- onEnabledChanged.subscribe(this) { value ->
- jobTracker.newUiJob("updateEnabled") {
- customDnsServersLock.withLock {
- enabled = value
- }
- }
+ fun updateState(isEnabled: Boolean) {
+ jobTracker.newUiJob("updateEnabled") {
+ customDnsServersLock.withLock {
+ enabled = isEnabled
}
}
}
@@ -108,7 +104,6 @@ class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>(
override fun onCreateViewHolder(parentView: ViewGroup, type: Int): CustomDnsItemHolder {
val inflater = LayoutInflater.from(parentView.context)
-
when (ViewTypes.values()[type]) {
ViewTypes.FOOTER -> {
val view = inflater.inflate(R.layout.custom_dns_footer, parentView, false)
@@ -144,13 +139,9 @@ class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>(
fun onDestroy() {
jobTracker.newBackgroundJob("toggleCustomDns") {
if (cachedCustomDnsServers.isEmpty()) {
- customDns.disable()
+ onSetCustomDnsEnabled(false)
}
}
- customDns.apply {
- onDnsServersChanged.unsubscribe(this)
- onEnabledChanged.unsubscribe(this)
- }
}
fun newDnsServer() {
@@ -227,7 +218,7 @@ class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>(
val position = jobTracker.runOnBackground {
val index = cachedCustomDnsServers.indexOf(address)
cachedCustomDnsServers.removeAt(index)
- customDns.removeDnsServer(address)
+ onRemoveDnsServer(address)
index
}
@@ -246,7 +237,7 @@ class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>(
var added = false
withValidAddress(addressText) { address ->
- if (customDns.addDnsServer(address)) {
+ if (onAddServer(address)) {
cachedCustomDnsServers.add(address)
added = true
}
@@ -270,7 +261,7 @@ class CustomDnsAdapter(val customDns: CustomDns) : Adapter<CustomDnsItemHolder>(
withValidAddress(address) { newAddress ->
val oldAddress = cachedCustomDnsServers[position]
- if (customDns.replaceDnsServer(oldAddress, newAddress)) {
+ if (onReplaceDnsServer(oldAddress, newAddress)) {
cachedCustomDnsServers[position] = newAddress
replaced = true
}