summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppListAdapter.kt4
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt2
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/service/SplitTunnelling.kt33
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SplitTunnellingFragment.kt50
4 files changed, 70 insertions, 19 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppListAdapter.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppListAdapter.kt
index 820ef12fb2..0fb1d94d47 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppListAdapter.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/applist/AppListAdapter.kt
@@ -35,7 +35,7 @@ class AppListAdapter(
init {
jobTracker.newBackgroundJob("populateAppList") {
- populateAppList(context)
+ populateAppList()
}
}
@@ -52,7 +52,7 @@ class AppListAdapter(
holder.appInfo = appList.get(position)
}
- private fun populateAppList(context: Context) {
+ private fun populateAppList() {
val applications = packageManager
.getInstalledApplications(0)
.filter { info -> info.packageName != thisPackageName }
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 317ca72eed..f4fb25a895 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
@@ -242,7 +242,7 @@ class MullvadVpnService : TalpidVpnService() {
pendingAction = null
}
- val splitTunnelling = SplitTunnelling().apply {
+ val splitTunnelling = SplitTunnelling(this).apply {
onChange = { excludedApps ->
disallowedApps = excludedApps
markTunAsStale()
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SplitTunnelling.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SplitTunnelling.kt
index 0722c2fc56..13f6b242f1 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SplitTunnelling.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/SplitTunnelling.kt
@@ -1,9 +1,16 @@
package net.mullvad.mullvadvpn.service
+import android.content.Context
+import java.io.File
import kotlin.properties.Delegates.observable
-class SplitTunnelling {
+private const val SHARED_PREFERENCES = "split_tunnelling"
+private const val KEY_ENABLED = "enabled"
+
+class SplitTunnelling(context: Context) {
+ private val appListFile = File(context.filesDir, "split-tunnelling.txt")
private val excludedApps = HashSet<String>()
+ private val preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE)
val excludedAppList
get() = if (enabled) {
@@ -12,9 +19,18 @@ class SplitTunnelling {
emptyList()
}
- var enabled by observable(false) { _, _, _ -> update() }
+ var enabled by observable(preferences.getBoolean(KEY_ENABLED, false)) { _, _, _ ->
+ enabledChanged()
+ }
+
var onChange: ((List<String>) -> Unit)? = null
+ init {
+ if (appListFile.exists()) {
+ excludedApps.addAll(appListFile.readLines())
+ }
+ }
+
fun isAppExcluded(appPackageName: String) = excludedApps.contains(appPackageName)
fun excludeApp(appPackageName: String) {
@@ -27,6 +43,19 @@ class SplitTunnelling {
update()
}
+ fun persist() {
+ appListFile.writeText(excludedApps.joinToString(separator = "\n"))
+ }
+
+ private fun enabledChanged() {
+ preferences.edit().apply {
+ putBoolean(KEY_ENABLED, enabled)
+ apply()
+ }
+
+ update()
+ }
+
private fun update() {
onChange?.invoke(excludedAppList)
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SplitTunnellingFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SplitTunnellingFragment.kt
index b94883798d..dc905abdbf 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SplitTunnellingFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SplitTunnellingFragment.kt
@@ -84,6 +84,12 @@ class SplitTunnellingFragment : ServiceDependentFragment(OnNoService.GoToLaunchS
return view
}
+ override fun onSafelyPause() {
+ jobTracker.newBackgroundJob("persistExcludedApps") {
+ splitTunnelling.persist()
+ }
+ }
+
override fun onSafelyDestroyView() {
titleController.onDestroy()
}
@@ -104,7 +110,20 @@ class SplitTunnellingFragment : ServiceDependentFragment(OnNoService.GoToLaunchS
setDuration(200)
}
+ if (configureSpinner()) {
+ jobTracker.newUiJob("enableAdapter") {
+ loadingSpinner.visibility = View.GONE
+ appListAdapter.enabled = true
+ }
+ }
+
enabledToggle = header.findViewById<CellSwitch>(R.id.enabled_toggle).apply {
+ if (splitTunnelling.enabled) {
+ forcefullySetState(CellSwitch.State.ON)
+ } else {
+ forcefullySetState(CellSwitch.State.OFF)
+ }
+
listener = { toggleState ->
when (toggleState) {
CellSwitch.State.ON -> enable()
@@ -119,29 +138,32 @@ class SplitTunnellingFragment : ServiceDependentFragment(OnNoService.GoToLaunchS
}
private fun enable() {
- appListAdapter.apply {
- if (!isListReady) {
- enabled = false
- showLoadingSpinner()
- onListReady = {
- hideLoadingSpinner()
- }
- } else {
- enabled = true
- }
- }
-
+ splitTunnelling.enabled = true
+ appListAdapter.enabled = configureSpinner()
excludeApplications.visibility = View.VISIBLE
excludeApplicationsFadeOut.reverse()
- splitTunnelling.enabled = true
}
private fun disable() {
- appListAdapter.enabled = false
splitTunnelling.enabled = false
+ appListAdapter.enabled = false
excludeApplicationsFadeOut.start()
}
+ private fun configureSpinner(): Boolean {
+ if (splitTunnelling.enabled && !appListAdapter.isListReady) {
+ showLoadingSpinner()
+
+ appListAdapter.onListReady = {
+ hideLoadingSpinner()
+ }
+
+ return false
+ } else {
+ return splitTunnelling.enabled
+ }
+ }
+
private fun showLoadingSpinner() {
loadingSpinner.visibility = View.VISIBLE
loadingSpinnerFadeIn.start()