summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2023-10-03 15:49:11 +0200
committerAlbin <albin@mullvad.net>2023-10-16 17:09:22 +0200
commit05a0a17332fe09ccea78eefcb323773732160ae0 (patch)
tree1a07755a52b925a4726ea5aabb729b9cbee17891 /android
parentdc70ef89771a89d1b978516e3415ddf5d50cc033 (diff)
downloadmullvadvpn-05a0a17332fe09ccea78eefcb323773732160ae0.tar.xz
mullvadvpn-05a0a17332fe09ccea78eefcb323773732160ae0.zip
Expose flexible ipc message handling
Diffstat (limited to 'android')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/MessageHandler.kt16
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt8
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt21
-rw-r--r--android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/DispatchingHandler.kt7
4 files changed, 51 insertions, 1 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/MessageHandler.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/MessageHandler.kt
new file mode 100644
index 0000000000..3bbcae9361
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/MessageHandler.kt
@@ -0,0 +1,16 @@
+package net.mullvad.mullvadvpn.ui.serviceconnection
+
+import kotlin.reflect.KClass
+import kotlinx.coroutines.flow.Flow
+import net.mullvad.mullvadvpn.lib.ipc.Event
+import net.mullvad.mullvadvpn.lib.ipc.Request
+
+interface MessageHandler {
+ fun <R : Event> events(klass: KClass<R>): Flow<R>
+
+ fun trySendRequest(request: Request): Boolean
+}
+
+inline fun <reified R : Event> MessageHandler.events(): Flow<R> {
+ return this.events(R::class)
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
index 6dbea7a517..93dcd75359 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt
@@ -4,9 +4,11 @@ import android.os.Looper
import android.os.Messenger
import android.os.RemoteException
import android.util.Log
+import kotlinx.coroutines.flow.filterIsInstance
import net.mullvad.mullvadvpn.lib.ipc.DispatchingHandler
import net.mullvad.mullvadvpn.lib.ipc.Event
import net.mullvad.mullvadvpn.lib.ipc.Request
+import net.mullvad.mullvadvpn.lib.ipc.extensions.trySendRequest
import org.koin.core.component.KoinComponent
// Container of classes that communicate with the service through an active connection
@@ -21,6 +23,8 @@ class ServiceConnectionContainer(
private val dispatcher =
DispatchingHandler(Looper.getMainLooper()) { message -> Event.fromMessage(message) }
+ val events = dispatcher.parsedMessages.filterIsInstance<Event>()
+
val accountDataSource = ServiceConnectionAccountDataSource(connection, dispatcher)
val authTokenCache = AuthTokenCache(connection, dispatcher)
val connectionProxy = ConnectionProxy(connection, dispatcher)
@@ -49,6 +53,10 @@ class ServiceConnectionContainer(
registerListener(connection)
}
+ fun trySendRequest(request: Request, logErrors: Boolean): Boolean {
+ return connection.trySendRequest(request, logErrors = logErrors)
+ }
+
fun onDestroy() {
unregisterListener()
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 0bbc4e71d4..d840b93491 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
@@ -6,15 +6,22 @@ import android.content.Intent
import android.os.IBinder
import android.os.Messenger
import android.util.Log
+import kotlin.reflect.KClass
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filterIsInstance
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.lib.ipc.Event
+import net.mullvad.mullvadvpn.lib.ipc.Request
import net.mullvad.mullvadvpn.service.MullvadVpnService
+import net.mullvad.mullvadvpn.util.flatMapReadyConnectionOrDefault
import net.mullvad.talpid.util.EventNotifier
-class ServiceConnectionManager(private val context: Context) {
+class ServiceConnectionManager(private val context: Context) : MessageHandler {
private val _connectionState =
MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Disconnected)
@@ -27,6 +34,9 @@ class ServiceConnectionManager(private val context: Context) {
var isBound = false
private var vpnPermissionRequestHandler: (() -> Unit)? = null
+ private val events =
+ connectionState.flatMapReadyConnectionOrDefault(emptyFlow()) { it.container.events }
+
private val serviceConnection =
object : android.content.ServiceConnection {
override fun onServiceConnected(className: ComponentName, binder: IBinder) {
@@ -82,6 +92,15 @@ class ServiceConnectionManager(private val context: Context) {
}
}
+ override fun <E : Event> events(klass: KClass<E>): Flow<E> {
+ return events.filterIsInstance(klass)
+ }
+
+ override fun trySendRequest(request: Request): Boolean {
+ return connectionState.value.readyContainer()?.trySendRequest(request, logErrors = false)
+ ?: false
+ }
+
fun onDestroy() {
_connectionState.value.readyContainer()?.onDestroy()
serviceNotifier.unsubscribeAll()
diff --git a/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/DispatchingHandler.kt b/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/DispatchingHandler.kt
index 7f6195c61e..dd73f3c156 100644
--- a/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/DispatchingHandler.kt
+++ b/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/DispatchingHandler.kt
@@ -7,12 +7,18 @@ import android.util.Log
import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.concurrent.withLock
import kotlin.reflect.KClass
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.asSharedFlow
class DispatchingHandler<T : Any>(looper: Looper, private val extractor: (Message) -> T?) :
Handler(looper), MessageDispatcher<T> {
private val handlers = HashMap<KClass<out T>, (T) -> Unit>()
private val lock = ReentrantReadWriteLock()
+ private val _parsedMessages = MutableSharedFlow<T>(extraBufferCapacity = 1)
+ val parsedMessages = _parsedMessages.asSharedFlow()
+
+ @Deprecated("Use parsedMessages instead.")
override fun <V : T> registerHandler(variant: KClass<V>, handler: (V) -> Unit) {
lock.writeLock().withLock {
handlers.put(variant) { instance -> @Suppress("UNCHECKED_CAST") handler(instance as V) }
@@ -27,6 +33,7 @@ class DispatchingHandler<T : Any>(looper: Looper, private val extractor: (Messag
val handler = handlers.get(instance::class)
handler?.invoke(instance)
+ _parsedMessages.tryEmit(instance)
} else {
Log.e("mullvad", "Dispatching handler received an unexpected message")
}