diff options
| author | David Göransson <david.goransson@mullvad.net> | 2024-08-30 13:54:11 +0200 |
|---|---|---|
| committer | David Göransson <david.goransson@mullvad.net> | 2024-08-30 13:54:11 +0200 |
| commit | b0c1bcc5b49aa83c80dc125980f8ab745008397e (patch) | |
| tree | b324a4dfcb01d4206f773390809ec4fc8b3a5b2c /android | |
| parent | 2c8d4f1be088c7d55526c5d2dea6e65bc6f94193 (diff) | |
| parent | 7f1fcf7503b5f0a8556d067dcf6e1bab443c849f (diff) | |
| download | mullvadvpn-b0c1bcc5b49aa83c80dc125980f8ab745008397e.tar.xz mullvadvpn-b0c1bcc5b49aa83c80dc125980f8ab745008397e.zip | |
Merge branch 'managementservicestop-sometimes-crashes-droid-1284'
Diffstat (limited to 'android')
14 files changed, 95 insertions, 117 deletions
diff --git a/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/constant/DiConstant.kt b/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/constant/DiConstant.kt index 0acd41c7ec..9fac18a479 100644 --- a/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/constant/DiConstant.kt +++ b/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/constant/DiConstant.kt @@ -1,3 +1,5 @@ package net.mullvad.mullvadvpn.lib.common.constant const val GRPC_SOCKET_FILE_NAMED_ARGUMENT = "RPC_SOCKET" +const val FILES_DIR_NAMED_ARGUMENT = "FILES_DIR" +const val CACHE_DIR_NAMED_ARGUMENT = "CACHE_DIR" diff --git a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpoint.kt b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpoint.kt deleted file mode 100644 index 1fd26bddae..0000000000 --- a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpoint.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.mullvad.mullvadvpn.lib.endpoint - -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, -) : Parcelable diff --git a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointConfiguration.kt b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointConfiguration.kt deleted file mode 100644 index 164a9fffa7..0000000000 --- a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointConfiguration.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.mullvad.mullvadvpn.lib.endpoint - -import android.os.Parcelable - -interface ApiEndpointConfiguration : Parcelable { - fun apiEndpoint(): ApiEndpoint? -} diff --git a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointIntentExtensions.kt b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointIntentExtensions.kt index cf2f2fb0dd..9e46c5dda8 100644 --- a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointIntentExtensions.kt +++ b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointIntentExtensions.kt @@ -5,13 +5,13 @@ import android.os.Build private const val OVERRIDE_API_EXTRA_NAME = "override_api" -fun Intent.putApiEndpointConfigurationExtra(apiEndpointConfiguration: ApiEndpointConfiguration) { - putExtra(OVERRIDE_API_EXTRA_NAME, apiEndpointConfiguration) +fun Intent.putApiEndpointConfigurationExtra(apiEndpointOverrideConfiguration: ApiEndpointOverride) { + putExtra(OVERRIDE_API_EXTRA_NAME, apiEndpointOverrideConfiguration) } -fun Intent.getApiEndpointConfigurationExtras(): ApiEndpointConfiguration? { +fun Intent.getApiEndpointConfigurationExtras(): ApiEndpointOverride? { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - getParcelableExtra(OVERRIDE_API_EXTRA_NAME, ApiEndpointConfiguration::class.java) + getParcelableExtra(OVERRIDE_API_EXTRA_NAME, ApiEndpointOverride::class.java) } else { getParcelableExtra(OVERRIDE_API_EXTRA_NAME) } diff --git a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointOverride.kt b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointOverride.kt new file mode 100644 index 0000000000..5201e86386 --- /dev/null +++ b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/ApiEndpointOverride.kt @@ -0,0 +1,17 @@ +package net.mullvad.mullvadvpn.lib.endpoint + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class ApiEndpointOverride( + val hostname: String, + val port: Int = CUSTOM_ENDPOINT_HTTPS_PORT, + val disableAddressCache: Boolean = true, + val disableTls: Boolean = false, + val forceDirectConnection: Boolean = true, +) : Parcelable { + companion object { + const val CUSTOM_ENDPOINT_HTTPS_PORT = 443 + } +} diff --git a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/CustomApiEndpointConfiguration.kt b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/CustomApiEndpointConfiguration.kt deleted file mode 100644 index 92dffed35f..0000000000 --- a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/CustomApiEndpointConfiguration.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.mullvad.mullvadvpn.lib.endpoint - -import java.net.InetSocketAddress -import kotlinx.parcelize.Parcelize - -const val CUSTOM_ENDPOINT_HTTPS_PORT = 443 - -@Parcelize -data class CustomApiEndpointConfiguration( - val hostname: String, - val port: Int, - val disableAddressCache: Boolean = true, - val disableTls: Boolean = false, -) : ApiEndpointConfiguration { - override fun apiEndpoint() = - ApiEndpoint( - address = InetSocketAddress(hostname, port), - disableAddressCache = disableAddressCache, - disableTls = disableTls, - ) -} diff --git a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/DefaultApiEndpointConfiguration.kt b/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/DefaultApiEndpointConfiguration.kt deleted file mode 100644 index 90b9bc7896..0000000000 --- a/android/lib/endpoint/src/main/kotlin/net/mullvad/mullvadvpn/lib/endpoint/DefaultApiEndpointConfiguration.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.mullvad.mullvadvpn.lib.endpoint - -import kotlinx.parcelize.Parcelize - -@Parcelize -class DefaultApiEndpointConfiguration : ApiEndpointConfiguration { - override fun apiEndpoint(): ApiEndpoint? = null -} diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonConfig.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonConfig.kt new file mode 100644 index 0000000000..06450a1583 --- /dev/null +++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/DaemonConfig.kt @@ -0,0 +1,11 @@ +package net.mullvad.mullvadvpn.service + +import java.io.File +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointOverride + +data class DaemonConfig( + val rpcSocket: File, + val filesDir: File, + val cacheDir: File, + val apiEndpointOverride: ApiEndpointOverride?, +) diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt index 5bfae14383..d95892305b 100644 --- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt +++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt @@ -1,6 +1,6 @@ package net.mullvad.mullvadvpn.service -import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpoint +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointOverride object MullvadDaemon { init { @@ -12,7 +12,7 @@ object MullvadDaemon { rpcSocketPath: String, filesDirectory: String, cacheDirectory: String, - apiEndpoint: ApiEndpoint?, + apiEndpointOverride: ApiEndpointOverride?, ) external fun shutdown() diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt index 5603392376..2b7833fb8d 100644 --- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt +++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt @@ -11,21 +11,17 @@ import androidx.lifecycle.lifecycleScope import arrow.atomic.AtomicInt import co.touchlab.kermit.Logger import java.io.File -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import net.mullvad.mullvadvpn.lib.common.constant.GRPC_SOCKET_FILE_NAMED_ARGUMENT import net.mullvad.mullvadvpn.lib.common.constant.KEY_CONNECT_ACTION import net.mullvad.mullvadvpn.lib.common.constant.KEY_DISCONNECT_ACTION import net.mullvad.mullvadvpn.lib.daemon.grpc.ManagementService -import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointConfiguration import net.mullvad.mullvadvpn.lib.endpoint.getApiEndpointConfigurationExtras import net.mullvad.mullvadvpn.lib.intent.IntentProvider import net.mullvad.mullvadvpn.lib.model.TunnelState import net.mullvad.mullvadvpn.lib.shared.ConnectionProxy -import net.mullvad.mullvadvpn.service.di.apiEndpointModule import net.mullvad.mullvadvpn.service.di.vpnServiceModule import net.mullvad.mullvadvpn.service.migration.MigrateSplitTunneling import net.mullvad.mullvadvpn.service.notifications.ForegroundNotificationManager @@ -34,7 +30,6 @@ import net.mullvad.mullvadvpn.service.notifications.NotificationManager import net.mullvad.talpid.TalpidVpnService import org.koin.android.ext.android.getKoin import org.koin.core.context.loadKoinModules -import org.koin.core.qualifier.named private const val RELAYS_FILE = "relays.json" @@ -42,12 +37,11 @@ class MullvadVpnService : TalpidVpnService() { private lateinit var keyguardManager: KeyguardManager - private lateinit var apiEndpointConfiguration: ApiEndpointConfiguration private lateinit var managementService: ManagementService private lateinit var migrateSplitTunneling: MigrateSplitTunneling private lateinit var intentProvider: IntentProvider private lateinit var connectionProxy: ConnectionProxy - private lateinit var rpcSocketFile: File + private lateinit var daemonConfig: DaemonConfig private lateinit var foregroundNotificationHandler: ForegroundNotificationManager @@ -59,7 +53,7 @@ class MullvadVpnService : TalpidVpnService() { super.onCreate() Logger.i("MullvadVpnService: onCreate") - loadKoinModules(listOf(vpnServiceModule, apiEndpointModule)) + loadKoinModules(listOf(vpnServiceModule)) with(getKoin()) { // Needed to create all the notification channels get<NotificationChannelFactory>() @@ -70,27 +64,32 @@ class MullvadVpnService : TalpidVpnService() { ForegroundNotificationManager(this@MullvadVpnService, get()) get<NotificationManager>() - apiEndpointConfiguration = get() + daemonConfig = get() migrateSplitTunneling = get() intentProvider = get() connectionProxy = get() - rpcSocketFile = get(named(GRPC_SOCKET_FILE_NAMED_ARGUMENT)) } keyguardManager = getSystemService<KeyguardManager>()!! - // TODO We should avoid lifecycleScope.launch (current needed due to InetSocketAddress - // with intent from API) - lifecycleScope.launch(context = Dispatchers.IO) { - prepareFiles(this@MullvadVpnService) - migrateSplitTunneling.migrate() + prepareFiles(this@MullvadVpnService) + migrateSplitTunneling.migrate() - Logger.i("Start daemon") - startDaemon() + // If it is a debug build and we have an api override in the intent, use it + // This is for injecting hostname and port for our mock api tests + val intentApiOverride = + intentProvider.getLatestIntent()?.getApiEndpointConfigurationExtras() + val updatedConfig = + if (BuildConfig.DEBUG && intentApiOverride != null) { + daemonConfig.copy(apiEndpointOverride = intentApiOverride) + } else { + daemonConfig + } + Logger.i("Start daemon") + startDaemon(updatedConfig) - Logger.i("Start management service") - managementService.start() - } + Logger.i("Start management service") + managementService.start() } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -147,24 +146,17 @@ class MullvadVpnService : TalpidVpnService() { } } - private fun startDaemon() { - val apiEndpointConfiguration = - if (BuildConfig.DEBUG) { - intentProvider.getLatestIntent()?.getApiEndpointConfigurationExtras() - ?: apiEndpointConfiguration - } else { - apiEndpointConfiguration - } - - MullvadDaemon.initialize( - vpnService = this@MullvadVpnService, - rpcSocketPath = rpcSocketFile.absolutePath, - filesDirectory = filesDir.absolutePath, - cacheDirectory = cacheDir.absolutePath, - apiEndpoint = apiEndpointConfiguration.apiEndpoint(), - ) - Logger.i("MullvadVpnService: Daemon initialized") - } + private fun startDaemon(daemonConfig: DaemonConfig) = + with(daemonConfig) { + MullvadDaemon.initialize( + vpnService = this@MullvadVpnService, + rpcSocketPath = rpcSocket.absolutePath, + filesDirectory = filesDir.absolutePath, + cacheDirectory = cacheDir.absolutePath, + apiEndpointOverride = apiEndpointOverride, + ) + Logger.i("MullvadVpnService: Daemon initialized") + } private fun emptyBinder() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/di/ApiEndpointModule.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/di/ApiEndpointModule.kt deleted file mode 100644 index 4d86559bc6..0000000000 --- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/di/ApiEndpointModule.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.mullvad.mullvadvpn.service.di - -import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointConfiguration -import net.mullvad.mullvadvpn.lib.endpoint.CUSTOM_ENDPOINT_HTTPS_PORT -import net.mullvad.mullvadvpn.lib.endpoint.CustomApiEndpointConfiguration -import net.mullvad.mullvadvpn.lib.endpoint.DefaultApiEndpointConfiguration -import net.mullvad.mullvadvpn.service.BuildConfig -import org.koin.dsl.bind -import org.koin.dsl.module - -val apiEndpointModule = module { - single { - if (BuildConfig.FLAVOR_infrastructure != "prod") { - CustomApiEndpointConfiguration(BuildConfig.API_ENDPOINT, CUSTOM_ENDPOINT_HTTPS_PORT) - } else { - DefaultApiEndpointConfiguration() - } - } bind ApiEndpointConfiguration::class -} diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/di/VpnServiceModule.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/di/VpnServiceModule.kt index e229e0ed24..9d4636cf07 100644 --- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/di/VpnServiceModule.kt +++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/di/VpnServiceModule.kt @@ -2,7 +2,13 @@ package net.mullvad.mullvadvpn.service.di import androidx.core.app.NotificationManagerCompat import kotlinx.coroutines.MainScope +import net.mullvad.mullvadvpn.lib.common.constant.CACHE_DIR_NAMED_ARGUMENT +import net.mullvad.mullvadvpn.lib.common.constant.FILES_DIR_NAMED_ARGUMENT +import net.mullvad.mullvadvpn.lib.common.constant.GRPC_SOCKET_FILE_NAMED_ARGUMENT +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointOverride import net.mullvad.mullvadvpn.lib.model.NotificationChannel +import net.mullvad.mullvadvpn.service.BuildConfig +import net.mullvad.mullvadvpn.service.DaemonConfig import net.mullvad.mullvadvpn.service.migration.MigrateSplitTunneling import net.mullvad.mullvadvpn.service.notifications.NotificationChannelFactory import net.mullvad.mullvadvpn.service.notifications.NotificationManager @@ -12,12 +18,15 @@ import net.mullvad.mullvadvpn.service.notifications.tunnelstate.TunnelStateNotif import org.koin.android.ext.koin.androidContext import org.koin.core.module.dsl.createdAtStart import org.koin.core.module.dsl.withOptions +import org.koin.core.qualifier.named import org.koin.dsl.bind import org.koin.dsl.module val vpnServiceModule = module { single { NotificationManagerCompat.from(androidContext()) } single { androidContext().resources } + single(named(FILES_DIR_NAMED_ARGUMENT)) { androidContext().filesDir } + single(named(CACHE_DIR_NAMED_ARGUMENT)) { androidContext().cacheDir } single { NotificationChannel.TunnelUpdates } bind NotificationChannel::class single { NotificationChannel.AccountUpdates } bind NotificationChannel::class @@ -46,4 +55,18 @@ val vpnServiceModule = module { } single { MigrateSplitTunneling(androidContext()) } + + single { + DaemonConfig( + rpcSocket = get(named(GRPC_SOCKET_FILE_NAMED_ARGUMENT)), + filesDir = get(named(FILES_DIR_NAMED_ARGUMENT)), + cacheDir = get(named(CACHE_DIR_NAMED_ARGUMENT)), + apiEndpointOverride = + if (BuildConfig.FLAVOR_infrastructure != "prod") { + ApiEndpointOverride(BuildConfig.API_ENDPOINT) + } else { + null + }, + ) + } } diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt index 9abd2aa7e2..5684b58e17 100644 --- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt +++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt @@ -6,7 +6,7 @@ import android.widget.Button import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until -import net.mullvad.mullvadvpn.lib.endpoint.CustomApiEndpointConfiguration +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointOverride import net.mullvad.mullvadvpn.lib.endpoint.putApiEndpointConfigurationExtra import net.mullvad.mullvadvpn.test.common.constant.APP_LAUNCH_TIMEOUT import net.mullvad.mullvadvpn.test.common.constant.CONNECTION_TIMEOUT @@ -23,7 +23,7 @@ class AppInteractor( private val targetContext: Context, private val targetPackageName: String, ) { - fun launch(customApiEndpointConfiguration: CustomApiEndpointConfiguration? = null) { + fun launch(customApiEndpointConfiguration: ApiEndpointOverride? = null) { device.pressHome() // Wait for launcher device.wait( diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt index bd236bb978..d3590fc056 100644 --- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt +++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt @@ -8,7 +8,7 @@ import androidx.test.uiautomator.UiDevice import co.touchlab.kermit.Logger import de.mannodermaus.junit5.extensions.GrantPermissionExtension import java.net.InetAddress -import net.mullvad.mullvadvpn.lib.endpoint.CustomApiEndpointConfiguration +import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointOverride import net.mullvad.mullvadvpn.test.common.interactor.AppInteractor import net.mullvad.mullvadvpn.test.common.rule.CaptureScreenshotOnFailedTestRule import net.mullvad.mullvadvpn.test.mockapi.constant.LOG_TAG @@ -33,7 +33,7 @@ abstract class MockApiTest { lateinit var device: UiDevice lateinit var targetContext: Context lateinit var app: AppInteractor - lateinit var endpoint: CustomApiEndpointConfiguration + lateinit var endpoint: ApiEndpointOverride @BeforeEach open fun setup() { @@ -54,8 +54,8 @@ abstract class MockApiTest { mockWebServer.shutdown() } - private fun createEndpoint(port: Int): CustomApiEndpointConfiguration { - return CustomApiEndpointConfiguration( + private fun createEndpoint(port: Int): ApiEndpointOverride { + return ApiEndpointOverride( InetAddress.getLocalHost().hostName, port, disableAddressCache = true, |
