diff options
| author | Albin <albin@mullvad.net> | 2023-01-10 15:58:10 +0100 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2023-01-10 15:58:10 +0100 |
| commit | 7ea38a3881b92b17658a5be4f0e627601212db6c (patch) | |
| tree | 96c12212b3f95c7ea588099aec7cb5fdb22942ed /android/app/src | |
| parent | fee3b5804555b3287c9c59aecd3682f118735ba8 (diff) | |
| parent | 57008a509342f547f5e56ef781a7f2e8a18298c0 (diff) | |
| download | mullvadvpn-7ea38a3881b92b17658a5be4f0e627601212db6c.tar.xz mullvadvpn-7ea38a3881b92b17658a5be4f0e627601212db6c.zip | |
Merge branch 'add-instrumented-tests-using-mocked-api'
Diffstat (limited to 'android/app/src')
| -rw-r--r-- | android/app/src/debug/AndroidManifest.xml | 4 | ||||
| -rw-r--r-- | android/app/src/debug/kotlin/net/mullvad/mullvadvpn/TestActivity.kt (renamed from android/app/src/debug/kotlin/net.mullvad.mullvadvpn/TestActivity.kt) | 0 | ||||
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/ApiEndpoint.kt | 13 | ||||
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonInstance.kt | 56 | ||||
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt | 14 | ||||
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt | 33 | ||||
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt | 8 | ||||
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt | 13 |
8 files changed, 86 insertions, 55 deletions
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 2a866ff601..e1a8f8be40 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,9 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> + + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + <application android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher" diff --git a/android/app/src/debug/kotlin/net.mullvad.mullvadvpn/TestActivity.kt b/android/app/src/debug/kotlin/net/mullvad/mullvadvpn/TestActivity.kt index df36947eab..df36947eab 100644 --- a/android/app/src/debug/kotlin/net.mullvad.mullvadvpn/TestActivity.kt +++ b/android/app/src/debug/kotlin/net/mullvad/mullvadvpn/TestActivity.kt diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/ApiEndpoint.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/ApiEndpoint.kt deleted file mode 100644 index df40bfac4d..0000000000 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/ApiEndpoint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.mullvad.mullvadvpn.model - -import android.os.Parcelable -import java.net.InetSocketAddress -import kotlinx.parcelize.Parcelize - -@Parcelize -data class ApiEndpoint( - val address: InetSocketAddress, - val disableAddressCache: Boolean, - val disableTls: Boolean, - val forceDirectConnection: Boolean -) : Parcelable diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonInstance.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonInstance.kt index 0d1750f625..67ec721a52 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonInstance.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonInstance.kt @@ -2,6 +2,8 @@ package net.mullvad.mullvadvpn.service import java.io.File import kotlin.properties.Delegates.observable +import kotlin.reflect.KClass +import kotlin.reflect.safeCast import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.channels.Channel @@ -9,14 +11,17 @@ import kotlinx.coroutines.channels.ClosedReceiveChannelException import kotlinx.coroutines.channels.ReceiveChannel import kotlinx.coroutines.channels.actor import kotlinx.coroutines.channels.trySendBlocking +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointConfiguration import net.mullvad.mullvadvpn.util.Intermittent private const val RELAYS_FILE = "relays.json" -class DaemonInstance(val vpnService: MullvadVpnService) { - private enum class Command { - START, - STOP, +class DaemonInstance( + val vpnService: MullvadVpnService +) { + sealed class Command { + data class Start(val apiEndpointConfiguration: ApiEndpointConfiguration) : Command() + object Stop : Command() } private val commandChannel = spawnActor() @@ -27,12 +32,12 @@ class DaemonInstance(val vpnService: MullvadVpnService) { val intermittentDaemon = Intermittent<MullvadDaemon>() - fun start() { - commandChannel.trySendBlocking(Command.START) + fun start(apiEndpointConfiguration: ApiEndpointConfiguration) { + commandChannel.trySendBlocking(Command.Start(apiEndpointConfiguration)) } fun stop() { - commandChannel.trySendBlocking(Command.STOP) + commandChannel.trySendBlocking(Command.Stop) } fun onDestroy() { @@ -46,30 +51,25 @@ class DaemonInstance(val vpnService: MullvadVpnService) { prepareFiles() while (isRunning) { - if (!waitForCommand(channel, Command.START)) { - break - } - - startDaemon() - - isRunning = waitForCommand(channel, Command.STOP) - + val startCommand = waitForCommand(channel, Command.Start::class) ?: break + startDaemon(startCommand.apiEndpointConfiguration) + isRunning = waitForCommand(channel, Command.Stop::class) is Command.Stop stopDaemon() } } - private suspend fun waitForCommand( + private suspend fun <T : Command> waitForCommand( channel: ReceiveChannel<Command>, - command: Command - ): Boolean { - try { - while (channel.receive() != command) { - // Wait for command - } - - return true + command: KClass<T> + ): T? { + return try { + var receivedCommand: T? + do { + receivedCommand = command.safeCast(channel.receive()) + } while (receivedCommand == null) + receivedCommand } catch (exception: ClosedReceiveChannelException) { - return false + null } } @@ -91,8 +91,10 @@ class DaemonInstance(val vpnService: MullvadVpnService) { } } - private suspend fun startDaemon() { - val newDaemon = MullvadDaemon(vpnService).apply { + private suspend fun startDaemon( + apiEndpointConfiguration: ApiEndpointConfiguration + ) { + val newDaemon = MullvadDaemon(vpnService, apiEndpointConfiguration).apply { onDaemonStopped = { intermittentDaemon.spawnUpdate(null) daemon = null diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt index aac23cee25..6d82ee617c 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt @@ -2,7 +2,8 @@ package net.mullvad.mullvadvpn.service import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow -import net.mullvad.mullvadvpn.model.ApiEndpoint +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpoint +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointConfiguration import net.mullvad.mullvadvpn.model.AppVersionInfo import net.mullvad.mullvadvpn.model.Device import net.mullvad.mullvadvpn.model.DeviceEvent @@ -21,7 +22,10 @@ import net.mullvad.mullvadvpn.model.TunnelState import net.mullvad.mullvadvpn.model.VoucherSubmissionResult import net.mullvad.talpid.util.EventNotifier -class MullvadDaemon(vpnService: MullvadVpnService) { +class MullvadDaemon( + vpnService: MullvadVpnService, + apiEndpointConfiguration: ApiEndpointConfiguration +) { protected var daemonInterfaceAddress = 0L val onSettingsChange = EventNotifier<Settings?>(null) @@ -39,8 +43,12 @@ class MullvadDaemon(vpnService: MullvadVpnService) { init { System.loadLibrary("mullvad_jni") + initialize( - vpnService, vpnService.cacheDir.absolutePath, vpnService.filesDir.absolutePath, null + vpnService = vpnService, + cacheDirectory = vpnService.cacheDir.absolutePath, + resourceDirectory = vpnService.filesDir.absolutePath, + apiEndpoint = apiEndpointConfiguration.apiEndpoint() ) onSettingsChange.notify(getSettings()) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt index 4753294376..c35125c326 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt @@ -12,7 +12,11 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.BuildConfig import net.mullvad.mullvadvpn.di.vpnServiceModule +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointConfiguration +import net.mullvad.mullvadvpn.lib.endpoint.DefaultApiEndpointConfiguration +import net.mullvad.mullvadvpn.lib.endpoint.getApiEndpointConfigurationExtras import net.mullvad.mullvadvpn.model.Settings import net.mullvad.mullvadvpn.model.TunnelState import net.mullvad.mullvadvpn.service.endpoint.ServiceEndpoint @@ -64,11 +68,15 @@ class MullvadVpnService : TalpidVpnService() { } } + private var apiEndpointConfiguration: ApiEndpointConfiguration = + DefaultApiEndpointConfiguration() + override fun onCreate() { super.onCreate() Log.d(TAG, "Initializing service") loadKoinModules(vpnServiceModule) + daemonInstance = DaemonInstance(this) keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager @@ -97,14 +105,6 @@ class MullvadVpnService : TalpidVpnService() { endpoint.accountCache ) - daemonInstance.apply { - intermittentDaemon.registerListener(this@MullvadVpnService) { daemon -> - handleDaemonInstance(daemon) - } - - start() - } - // Remove any leftover tunnel state persistence data getSharedPreferences("tunnel_state", MODE_PRIVATE) .edit() @@ -114,6 +114,21 @@ class MullvadVpnService : TalpidVpnService() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.d(TAG, "Starting service") + + if (BuildConfig.DEBUG) { + intent?.getApiEndpointConfigurationExtras()?.let { + apiEndpointConfiguration = it + } + } + + daemonInstance.apply { + intermittentDaemon.registerListener(this@MullvadVpnService) { daemon -> + handleDaemonInstance(daemon) + } + + start(apiEndpointConfiguration) + } + val startResult = super.onStartCommand(intent, flags, startId) var quitCommand = false @@ -231,7 +246,7 @@ class MullvadVpnService : TalpidVpnService() { daemonInstance.apply { stop() - start() + start(apiEndpointConfiguration) } } else { Log.d(TAG, "Ignoring restart because onDestroy has executed") diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt index becf82a69e..fc53d94aaf 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt @@ -22,7 +22,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first @@ -34,6 +33,7 @@ import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.compose.component.ChangelogDialog import net.mullvad.mullvadvpn.dataproxy.MullvadProblemReport import net.mullvad.mullvadvpn.di.uiModule +import net.mullvad.mullvadvpn.lib.endpoint.getApiEndpointConfigurationExtras import net.mullvad.mullvadvpn.model.AccountExpiry import net.mullvad.mullvadvpn.model.DeviceState import net.mullvad.mullvadvpn.ui.fragments.DeviceRevokedFragment @@ -103,7 +103,11 @@ open class MainActivity : FragmentActivity() { override fun onStart() { Log.d("mullvad", "Starting main activity") super.onStart() - serviceConnectionManager.bind(vpnPermissionRequestHandler = ::requestVpnPermission) + + serviceConnectionManager.bind( + vpnPermissionRequestHandler = ::requestVpnPermission, + apiEndpointConfiguration = intent?.getApiEndpointConfigurationExtras() + ) } override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt index e1654476b8..f912f765a8 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt @@ -8,6 +8,9 @@ import android.os.Messenger import android.util.Log import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointConfiguration +import net.mullvad.mullvadvpn.lib.endpoint.BuildConfig +import net.mullvad.mullvadvpn.lib.endpoint.putApiEndpointConfigurationExtra import net.mullvad.mullvadvpn.service.MullvadVpnService import net.mullvad.talpid.util.EventNotifier @@ -47,9 +50,17 @@ class ServiceConnectionManager( } } - fun bind(vpnPermissionRequestHandler: () -> Unit) { + fun bind( + vpnPermissionRequestHandler: () -> Unit, + apiEndpointConfiguration: ApiEndpointConfiguration? + ) { this.vpnPermissionRequestHandler = vpnPermissionRequestHandler val intent = Intent(context, MullvadVpnService::class.java) + + if (BuildConfig.DEBUG && apiEndpointConfiguration != null) { + intent.putApiEndpointConfigurationExtra(apiEndpointConfiguration) + } + context.startService(intent) context.bindService(intent, serviceConnection, 0) } |
